Loading core/java/android/text/util/Linkify.java +2 −1 Original line number Diff line number Diff line Loading @@ -650,7 +650,8 @@ public class Linkify { final CharSequence truncatedText = text.subSequence( 0, Math.min(text.length(), classifier.getMaxGenerateLinksTextLength())); final Supplier<TextLinks> supplier = () -> classifier.generateLinks(truncatedText, options); final Supplier<TextLinks> supplier = () -> classifier.generateLinks(truncatedText, options.setLegacyFallback(true)); final Consumer<TextLinks> consumer = links -> { if (links.getLinks().isEmpty()) { if (callback != null) { Loading core/java/android/view/textclassifier/SystemTextClassifier.java +10 −5 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ import android.service.textclassifier.ITextLinksCallback; import android.service.textclassifier.ITextSelectionCallback; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting.Visibility; import com.android.internal.util.Preconditions; import java.util.concurrent.CountDownLatch; Loading @@ -37,8 +39,10 @@ import java.util.concurrent.TimeUnit; /** * Proxy to the system's default TextClassifier. * @hide */ final class SystemTextClassifier implements TextClassifier { @VisibleForTesting(visibility = Visibility.PACKAGE) public final class SystemTextClassifier implements TextClassifier { private static final String LOG_TAG = "SystemTextClassifier"; Loading @@ -53,13 +57,13 @@ final class SystemTextClassifier implements TextClassifier { @GuardedBy("mLoggerLock") private Logger mLogger; SystemTextClassifier(Context context, TextClassificationConstants settings) public SystemTextClassifier(Context context, TextClassificationConstants settings) throws ServiceManager.ServiceNotFoundException { mManagerService = ITextClassifierService.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.TEXT_CLASSIFICATION_SERVICE)); mSettings = Preconditions.checkNotNull(settings); mFallback = new TextClassifierImpl(context, settings); mPackageName = context.getPackageName(); mPackageName = Preconditions.checkNotNull(context.getPackageName()); } /** Loading Loading @@ -124,8 +128,9 @@ final class SystemTextClassifier implements TextClassifier { @NonNull CharSequence text, @Nullable TextLinks.Options options) { Utils.validate(text, false /* allowInMainThread */); if (!mSettings.isSmartLinkifyEnabled()) { return TextClassifier.NO_OP.generateLinks(text, options); final boolean legacyFallback = options != null && options.isLegacyFallback(); if (!mSettings.isSmartLinkifyEnabled() && legacyFallback) { return Utils.generateLegacyLinks(text, options); } try { Loading core/java/android/view/textclassifier/TextClassification.java +19 −0 Original line number Diff line number Diff line Loading @@ -344,6 +344,25 @@ public final class TextClassification implements Parcelable { } } /** * Triggers the specified intent. * * @throws IllegalArgumentException if context or intent is null * @hide */ public static void fireIntent(@NonNull final Context context, @NonNull final Intent intent) { switch (getIntentType(intent, context)) { case IntentType.ACTIVITY: context.startActivity(intent); return; case IntentType.SERVICE: context.startService(intent); return; default: return; } } @IntentType private static int getIntentType(@NonNull Intent intent, @NonNull Context context) { Preconditions.checkArgument(context != null); Loading core/java/android/view/textclassifier/TextClassifier.java +66 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,12 @@ import android.os.LocaleList; import android.os.Looper; import android.os.Parcel; import android.os.Parcelable; import android.text.Spannable; import android.text.SpannableString; import android.text.style.URLSpan; import android.text.util.Linkify; import android.text.util.Linkify.LinkifyMask; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; Loading @@ -37,6 +43,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; /** * Interface for providing text classification related features. Loading Loading @@ -511,6 +518,65 @@ public interface TextClassifier { Preconditions.checkArgumentInRange(text.length(), 0, maxLength, "text.length()"); } /** * Generates links using legacy {@link Linkify}. */ public static TextLinks generateLegacyLinks( @NonNull CharSequence text, @NonNull TextLinks.Options options) { final String string = Preconditions.checkNotNull(text).toString(); final TextLinks.Builder links = new TextLinks.Builder(string); final List<String> entities = Preconditions.checkNotNull(options).getEntityConfig() .resolveEntityListModifications(Collections.emptyList()); if (entities.contains(TextClassifier.TYPE_URL)) { addLinks(links, string, TextClassifier.TYPE_URL); } if (entities.contains(TextClassifier.TYPE_PHONE)) { addLinks(links, string, TextClassifier.TYPE_PHONE); } if (entities.contains(TextClassifier.TYPE_EMAIL)) { addLinks(links, string, TextClassifier.TYPE_EMAIL); } // NOTE: Do not support MAP_ADDRESSES. Legacy version does not work well. return links.build(); } private static void addLinks( TextLinks.Builder links, String string, @EntityType String entityType) { final Spannable spannable = new SpannableString(string); if (Linkify.addLinks(spannable, linkMask(entityType))) { final URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class); for (URLSpan urlSpan : spans) { links.addLink( spannable.getSpanStart(urlSpan), spannable.getSpanEnd(urlSpan), entityScores(entityType), urlSpan); } } } @LinkifyMask private static int linkMask(@EntityType String entityType) { switch (entityType) { case TextClassifier.TYPE_URL: return Linkify.WEB_URLS; case TextClassifier.TYPE_PHONE: return Linkify.PHONE_NUMBERS; case TextClassifier.TYPE_EMAIL: return Linkify.EMAIL_ADDRESSES; default: // NOTE: Do not support MAP_ADDRESSES. Legacy version does not work well. return 0; } } private static Map<String, Float> entityScores(@EntityType String entityType) { final Map<String, Float> scores = new ArrayMap<>(); scores.put(entityType, 1f); return scores; } private static void checkMainThread(boolean allowInMainThread) { if (!allowInMainThread && Looper.myLooper() == Looper.getMainLooper()) { Slog.w(DEFAULT_LOG_TAG, "TextClassifier called on main thread"); Loading core/java/android/view/textclassifier/TextClassifierImpl.java +6 −4 Original line number Diff line number Diff line Loading @@ -209,13 +209,15 @@ public final class TextClassifierImpl implements TextClassifier { public TextLinks generateLinks( @NonNull CharSequence text, @Nullable TextLinks.Options options) { Utils.validate(text, getMaxGenerateLinksTextLength(), false /* allowInMainThread */); final String textString = text.toString(); final TextLinks.Builder builder = new TextLinks.Builder(textString); if (!mSettings.isSmartLinkifyEnabled()) { return builder.build(); final boolean legacyFallback = options != null && options.isLegacyFallback(); if (!mSettings.isSmartLinkifyEnabled() && legacyFallback) { return Utils.generateLegacyLinks(text, options); } final String textString = text.toString(); final TextLinks.Builder builder = new TextLinks.Builder(textString); try { final long startTimeMs = System.currentTimeMillis(); final LocaleList defaultLocales = options != null ? options.getDefaultLocales() : null; Loading Loading
core/java/android/text/util/Linkify.java +2 −1 Original line number Diff line number Diff line Loading @@ -650,7 +650,8 @@ public class Linkify { final CharSequence truncatedText = text.subSequence( 0, Math.min(text.length(), classifier.getMaxGenerateLinksTextLength())); final Supplier<TextLinks> supplier = () -> classifier.generateLinks(truncatedText, options); final Supplier<TextLinks> supplier = () -> classifier.generateLinks(truncatedText, options.setLegacyFallback(true)); final Consumer<TextLinks> consumer = links -> { if (links.getLinks().isEmpty()) { if (callback != null) { Loading
core/java/android/view/textclassifier/SystemTextClassifier.java +10 −5 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ import android.service.textclassifier.ITextLinksCallback; import android.service.textclassifier.ITextSelectionCallback; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting.Visibility; import com.android.internal.util.Preconditions; import java.util.concurrent.CountDownLatch; Loading @@ -37,8 +39,10 @@ import java.util.concurrent.TimeUnit; /** * Proxy to the system's default TextClassifier. * @hide */ final class SystemTextClassifier implements TextClassifier { @VisibleForTesting(visibility = Visibility.PACKAGE) public final class SystemTextClassifier implements TextClassifier { private static final String LOG_TAG = "SystemTextClassifier"; Loading @@ -53,13 +57,13 @@ final class SystemTextClassifier implements TextClassifier { @GuardedBy("mLoggerLock") private Logger mLogger; SystemTextClassifier(Context context, TextClassificationConstants settings) public SystemTextClassifier(Context context, TextClassificationConstants settings) throws ServiceManager.ServiceNotFoundException { mManagerService = ITextClassifierService.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.TEXT_CLASSIFICATION_SERVICE)); mSettings = Preconditions.checkNotNull(settings); mFallback = new TextClassifierImpl(context, settings); mPackageName = context.getPackageName(); mPackageName = Preconditions.checkNotNull(context.getPackageName()); } /** Loading Loading @@ -124,8 +128,9 @@ final class SystemTextClassifier implements TextClassifier { @NonNull CharSequence text, @Nullable TextLinks.Options options) { Utils.validate(text, false /* allowInMainThread */); if (!mSettings.isSmartLinkifyEnabled()) { return TextClassifier.NO_OP.generateLinks(text, options); final boolean legacyFallback = options != null && options.isLegacyFallback(); if (!mSettings.isSmartLinkifyEnabled() && legacyFallback) { return Utils.generateLegacyLinks(text, options); } try { Loading
core/java/android/view/textclassifier/TextClassification.java +19 −0 Original line number Diff line number Diff line Loading @@ -344,6 +344,25 @@ public final class TextClassification implements Parcelable { } } /** * Triggers the specified intent. * * @throws IllegalArgumentException if context or intent is null * @hide */ public static void fireIntent(@NonNull final Context context, @NonNull final Intent intent) { switch (getIntentType(intent, context)) { case IntentType.ACTIVITY: context.startActivity(intent); return; case IntentType.SERVICE: context.startService(intent); return; default: return; } } @IntentType private static int getIntentType(@NonNull Intent intent, @NonNull Context context) { Preconditions.checkArgument(context != null); Loading
core/java/android/view/textclassifier/TextClassifier.java +66 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,12 @@ import android.os.LocaleList; import android.os.Looper; import android.os.Parcel; import android.os.Parcelable; import android.text.Spannable; import android.text.SpannableString; import android.text.style.URLSpan; import android.text.util.Linkify; import android.text.util.Linkify.LinkifyMask; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; Loading @@ -37,6 +43,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; /** * Interface for providing text classification related features. Loading Loading @@ -511,6 +518,65 @@ public interface TextClassifier { Preconditions.checkArgumentInRange(text.length(), 0, maxLength, "text.length()"); } /** * Generates links using legacy {@link Linkify}. */ public static TextLinks generateLegacyLinks( @NonNull CharSequence text, @NonNull TextLinks.Options options) { final String string = Preconditions.checkNotNull(text).toString(); final TextLinks.Builder links = new TextLinks.Builder(string); final List<String> entities = Preconditions.checkNotNull(options).getEntityConfig() .resolveEntityListModifications(Collections.emptyList()); if (entities.contains(TextClassifier.TYPE_URL)) { addLinks(links, string, TextClassifier.TYPE_URL); } if (entities.contains(TextClassifier.TYPE_PHONE)) { addLinks(links, string, TextClassifier.TYPE_PHONE); } if (entities.contains(TextClassifier.TYPE_EMAIL)) { addLinks(links, string, TextClassifier.TYPE_EMAIL); } // NOTE: Do not support MAP_ADDRESSES. Legacy version does not work well. return links.build(); } private static void addLinks( TextLinks.Builder links, String string, @EntityType String entityType) { final Spannable spannable = new SpannableString(string); if (Linkify.addLinks(spannable, linkMask(entityType))) { final URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class); for (URLSpan urlSpan : spans) { links.addLink( spannable.getSpanStart(urlSpan), spannable.getSpanEnd(urlSpan), entityScores(entityType), urlSpan); } } } @LinkifyMask private static int linkMask(@EntityType String entityType) { switch (entityType) { case TextClassifier.TYPE_URL: return Linkify.WEB_URLS; case TextClassifier.TYPE_PHONE: return Linkify.PHONE_NUMBERS; case TextClassifier.TYPE_EMAIL: return Linkify.EMAIL_ADDRESSES; default: // NOTE: Do not support MAP_ADDRESSES. Legacy version does not work well. return 0; } } private static Map<String, Float> entityScores(@EntityType String entityType) { final Map<String, Float> scores = new ArrayMap<>(); scores.put(entityType, 1f); return scores; } private static void checkMainThread(boolean allowInMainThread) { if (!allowInMainThread && Looper.myLooper() == Looper.getMainLooper()) { Slog.w(DEFAULT_LOG_TAG, "TextClassifier called on main thread"); Loading
core/java/android/view/textclassifier/TextClassifierImpl.java +6 −4 Original line number Diff line number Diff line Loading @@ -209,13 +209,15 @@ public final class TextClassifierImpl implements TextClassifier { public TextLinks generateLinks( @NonNull CharSequence text, @Nullable TextLinks.Options options) { Utils.validate(text, getMaxGenerateLinksTextLength(), false /* allowInMainThread */); final String textString = text.toString(); final TextLinks.Builder builder = new TextLinks.Builder(textString); if (!mSettings.isSmartLinkifyEnabled()) { return builder.build(); final boolean legacyFallback = options != null && options.isLegacyFallback(); if (!mSettings.isSmartLinkifyEnabled() && legacyFallback) { return Utils.generateLegacyLinks(text, options); } final String textString = text.toString(); final TextLinks.Builder builder = new TextLinks.Builder(textString); try { final long startTimeMs = System.currentTimeMillis(); final LocaleList defaultLocales = options != null ? options.getDefaultLocales() : null; Loading