Loading core/java/android/text/util/Linkify.java +36 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.text.style.URLSpan; import android.text.Spannable; import android.text.SpannableString; import android.text.Spanned; import android.util.Log; import android.util.Patterns; import android.webkit.WebView; import android.widget.TextView; Loading Loading @@ -65,6 +66,9 @@ import libcore.util.EmptyArray; */ public class Linkify { private static final String LOG_TAG = "Linkify"; /** * Bit field indicating that web URLs should be matched in methods that * take an options mask Loading Loading @@ -222,6 +226,11 @@ public class Linkify { * @return True if at least one link is found and applied. */ public static final boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask) { if (text != null && containsUnsupportedCharacters(text.toString())) { android.util.EventLog.writeEvent(0x534e4554, "116321860", -1, ""); return false; } if (mask == 0) { return false; } Loading Loading @@ -267,6 +276,29 @@ public class Linkify { return true; } /** * Returns true if the specified text contains at least one unsupported character for applying * links. Also logs the error. * * @param text the text to apply links to * @hide */ public static boolean containsUnsupportedCharacters(String text) { if (text.contains("\u202C")) { Log.e(LOG_TAG, "Unsupported character for applying links: u202C"); return true; } if (text.contains("\u202D")) { Log.e(LOG_TAG, "Unsupported character for applying links: u202D"); return true; } if (text.contains("\u202E")) { Log.e(LOG_TAG, "Unsupported character for applying links: u202E"); return true; } return false; } /** * Scans the text of the provided TextView and turns all occurrences of * the link types indicated in the mask into clickable links. If matches Loading Loading @@ -414,6 +446,10 @@ public class Linkify { public static final boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern, @Nullable String scheme, @Nullable MatchFilter matchFilter, @Nullable TransformFilter transformFilter) { if (spannable != null && containsUnsupportedCharacters(spannable.toString())) { android.util.EventLog.writeEvent(0x534e4554, "116321860", -1, ""); return false; } return addLinks(spannable, pattern, scheme, null, matchFilter, transformFilter); } Loading services/core/java/com/android/server/TextServicesManagerService.java +17 −9 Original line number Diff line number Diff line Loading @@ -183,7 +183,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap, mSettings); SpellCheckerInfo sci = getCurrentSpellChecker(null); if (sci == null) { sci = findAvailSpellCheckerLocked(null); sci = findAvailSystemSpellCheckerLocked(null); if (sci != null) { // Set the current spell checker if there is one or more spell checkers // available. In this case, "sci" is the first one in the available spell Loading Loading @@ -227,7 +227,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE // Package modified || isPackageModified(packageName)) { sci = findAvailSpellCheckerLocked(packageName); sci = findAvailSystemSpellCheckerLocked(packageName); if (sci != null) { setCurrentSpellCheckerLocked(sci.getId()); } Loading Loading @@ -371,18 +371,26 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { mSpellCheckerBindGroups.clear(); } private SpellCheckerInfo findAvailSpellCheckerLocked(String prefPackage) { final int spellCheckersCount = mSpellCheckerList.size(); private SpellCheckerInfo findAvailSystemSpellCheckerLocked(String prefPackage) { // Filter the spell checker list to remove spell checker services that are not pre-installed ArrayList<SpellCheckerInfo> spellCheckerList = new ArrayList<>(); for (SpellCheckerInfo sci : mSpellCheckerList) { if ((sci.getServiceInfo().applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { spellCheckerList.add(sci); } } final int spellCheckersCount = spellCheckerList.size(); if (spellCheckersCount == 0) { Slog.w(TAG, "no available spell checker services found"); return null; } if (prefPackage != null) { for (int i = 0; i < spellCheckersCount; ++i) { final SpellCheckerInfo sci = mSpellCheckerList.get(i); final SpellCheckerInfo sci = spellCheckerList.get(i); if (prefPackage.equals(sci.getPackageName())) { if (DBG) { Slog.d(TAG, "findAvailSpellCheckerLocked: " + sci.getPackageName()); Slog.d(TAG, "findAvailSystemSpellCheckerLocked: " + sci.getPackageName()); } return sci; } Loading @@ -396,7 +404,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { final ArrayList<Locale> suitableLocales = InputMethodUtils.getSuitableLocalesForSpellChecker(systemLocal); if (DBG) { Slog.w(TAG, "findAvailSpellCheckerLocked suitableLocales=" Slog.w(TAG, "findAvailSystemSpellCheckerLocked suitableLocales=" + Arrays.toString(suitableLocales.toArray(new Locale[suitableLocales.size()]))); } final int localeCount = suitableLocales.size(); Loading @@ -404,7 +412,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { final Locale locale = suitableLocales.get(localeIndex); for (int spellCheckersIndex = 0; spellCheckersIndex < spellCheckersCount; ++spellCheckersIndex) { final SpellCheckerInfo info = mSpellCheckerList.get(spellCheckersIndex); final SpellCheckerInfo info = spellCheckerList.get(spellCheckersIndex); final int subtypeCount = info.getSubtypeCount(); for (int subtypeIndex = 0; subtypeIndex < subtypeCount; ++subtypeIndex) { final SpellCheckerSubtype subtype = info.getSubtypeAt(subtypeIndex); Loading @@ -423,7 +431,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { if (spellCheckersCount > 1) { Slog.w(TAG, "more than one spell checker service found, picking first"); } return mSpellCheckerList.get(0); return spellCheckerList.get(0); } // TODO: Save SpellCheckerService by supported languages. Currently only one spell Loading Loading
core/java/android/text/util/Linkify.java +36 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.text.style.URLSpan; import android.text.Spannable; import android.text.SpannableString; import android.text.Spanned; import android.util.Log; import android.util.Patterns; import android.webkit.WebView; import android.widget.TextView; Loading Loading @@ -65,6 +66,9 @@ import libcore.util.EmptyArray; */ public class Linkify { private static final String LOG_TAG = "Linkify"; /** * Bit field indicating that web URLs should be matched in methods that * take an options mask Loading Loading @@ -222,6 +226,11 @@ public class Linkify { * @return True if at least one link is found and applied. */ public static final boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask) { if (text != null && containsUnsupportedCharacters(text.toString())) { android.util.EventLog.writeEvent(0x534e4554, "116321860", -1, ""); return false; } if (mask == 0) { return false; } Loading Loading @@ -267,6 +276,29 @@ public class Linkify { return true; } /** * Returns true if the specified text contains at least one unsupported character for applying * links. Also logs the error. * * @param text the text to apply links to * @hide */ public static boolean containsUnsupportedCharacters(String text) { if (text.contains("\u202C")) { Log.e(LOG_TAG, "Unsupported character for applying links: u202C"); return true; } if (text.contains("\u202D")) { Log.e(LOG_TAG, "Unsupported character for applying links: u202D"); return true; } if (text.contains("\u202E")) { Log.e(LOG_TAG, "Unsupported character for applying links: u202E"); return true; } return false; } /** * Scans the text of the provided TextView and turns all occurrences of * the link types indicated in the mask into clickable links. If matches Loading Loading @@ -414,6 +446,10 @@ public class Linkify { public static final boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern, @Nullable String scheme, @Nullable MatchFilter matchFilter, @Nullable TransformFilter transformFilter) { if (spannable != null && containsUnsupportedCharacters(spannable.toString())) { android.util.EventLog.writeEvent(0x534e4554, "116321860", -1, ""); return false; } return addLinks(spannable, pattern, scheme, null, matchFilter, transformFilter); } Loading
services/core/java/com/android/server/TextServicesManagerService.java +17 −9 Original line number Diff line number Diff line Loading @@ -183,7 +183,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap, mSettings); SpellCheckerInfo sci = getCurrentSpellChecker(null); if (sci == null) { sci = findAvailSpellCheckerLocked(null); sci = findAvailSystemSpellCheckerLocked(null); if (sci != null) { // Set the current spell checker if there is one or more spell checkers // available. In this case, "sci" is the first one in the available spell Loading Loading @@ -227,7 +227,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE // Package modified || isPackageModified(packageName)) { sci = findAvailSpellCheckerLocked(packageName); sci = findAvailSystemSpellCheckerLocked(packageName); if (sci != null) { setCurrentSpellCheckerLocked(sci.getId()); } Loading Loading @@ -371,18 +371,26 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { mSpellCheckerBindGroups.clear(); } private SpellCheckerInfo findAvailSpellCheckerLocked(String prefPackage) { final int spellCheckersCount = mSpellCheckerList.size(); private SpellCheckerInfo findAvailSystemSpellCheckerLocked(String prefPackage) { // Filter the spell checker list to remove spell checker services that are not pre-installed ArrayList<SpellCheckerInfo> spellCheckerList = new ArrayList<>(); for (SpellCheckerInfo sci : mSpellCheckerList) { if ((sci.getServiceInfo().applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { spellCheckerList.add(sci); } } final int spellCheckersCount = spellCheckerList.size(); if (spellCheckersCount == 0) { Slog.w(TAG, "no available spell checker services found"); return null; } if (prefPackage != null) { for (int i = 0; i < spellCheckersCount; ++i) { final SpellCheckerInfo sci = mSpellCheckerList.get(i); final SpellCheckerInfo sci = spellCheckerList.get(i); if (prefPackage.equals(sci.getPackageName())) { if (DBG) { Slog.d(TAG, "findAvailSpellCheckerLocked: " + sci.getPackageName()); Slog.d(TAG, "findAvailSystemSpellCheckerLocked: " + sci.getPackageName()); } return sci; } Loading @@ -396,7 +404,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { final ArrayList<Locale> suitableLocales = InputMethodUtils.getSuitableLocalesForSpellChecker(systemLocal); if (DBG) { Slog.w(TAG, "findAvailSpellCheckerLocked suitableLocales=" Slog.w(TAG, "findAvailSystemSpellCheckerLocked suitableLocales=" + Arrays.toString(suitableLocales.toArray(new Locale[suitableLocales.size()]))); } final int localeCount = suitableLocales.size(); Loading @@ -404,7 +412,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { final Locale locale = suitableLocales.get(localeIndex); for (int spellCheckersIndex = 0; spellCheckersIndex < spellCheckersCount; ++spellCheckersIndex) { final SpellCheckerInfo info = mSpellCheckerList.get(spellCheckersIndex); final SpellCheckerInfo info = spellCheckerList.get(spellCheckersIndex); final int subtypeCount = info.getSubtypeCount(); for (int subtypeIndex = 0; subtypeIndex < subtypeCount; ++subtypeIndex) { final SpellCheckerSubtype subtype = info.getSubtypeAt(subtypeIndex); Loading @@ -423,7 +431,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { if (spellCheckersCount > 1) { Slog.w(TAG, "more than one spell checker service found, picking first"); } return mSpellCheckerList.get(0); return spellCheckerList.get(0); } // TODO: Save SpellCheckerService by supported languages. Currently only one spell Loading