diff --git a/core/api/current.txt b/core/api/current.txt index 1b519dc2c9e79..ff13694b09f5e 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -52715,6 +52715,22 @@ package android.view.textservice { method public void onGetSuggestions(android.view.textservice.SuggestionsInfo[]); } + public static class SpellCheckerSession.SpellCheckerSessionParams { + method @NonNull public android.os.Bundle getExtras(); + method @Nullable public java.util.Locale getLocale(); + method public int getSupportedAttributes(); + method public boolean shouldReferToSpellCheckerLanguageSettings(); + } + + public static final class SpellCheckerSession.SpellCheckerSessionParams.Builder { + ctor public SpellCheckerSession.SpellCheckerSessionParams.Builder(); + method @NonNull public android.view.textservice.SpellCheckerSession.SpellCheckerSessionParams build(); + method @NonNull public android.view.textservice.SpellCheckerSession.SpellCheckerSessionParams.Builder setExtras(@NonNull android.os.Bundle); + method @NonNull public android.view.textservice.SpellCheckerSession.SpellCheckerSessionParams.Builder setLocale(@Nullable java.util.Locale); + method @NonNull public android.view.textservice.SpellCheckerSession.SpellCheckerSessionParams.Builder setShouldReferToSpellCheckerLanguageSettings(boolean); + method @NonNull public android.view.textservice.SpellCheckerSession.SpellCheckerSessionParams.Builder setSupportedAttributes(int); + } + public final class SpellCheckerSubtype implements android.os.Parcelable { ctor @Deprecated public SpellCheckerSubtype(int, String, String); method public boolean containsExtraValueKey(String); @@ -52768,7 +52784,7 @@ package android.view.textservice { method @NonNull public java.util.List getEnabledSpellCheckerInfos(); method public boolean isSpellCheckerEnabled(); method @Nullable public android.view.textservice.SpellCheckerSession newSpellCheckerSession(@Nullable android.os.Bundle, @Nullable java.util.Locale, @NonNull android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener, boolean); - method @Nullable public android.view.textservice.SpellCheckerSession newSpellCheckerSession(@Nullable java.util.Locale, boolean, int, @Nullable android.os.Bundle, @NonNull java.util.concurrent.Executor, @NonNull android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener); + method @Nullable public android.view.textservice.SpellCheckerSession newSpellCheckerSession(@NonNull android.view.textservice.SpellCheckerSession.SpellCheckerSessionParams, @NonNull java.util.concurrent.Executor, @NonNull android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener); } } diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java index a449cf1876e12..6cfb9381f1308 100644 --- a/core/java/android/view/textservice/SpellCheckerSession.java +++ b/core/java/android/view/textservice/SpellCheckerSession.java @@ -17,10 +17,13 @@ package android.view.textservice; import android.annotation.BinderThread; +import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.compat.annotation.UnsupportedAppUsage; import android.os.Binder; import android.os.Build; +import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; @@ -37,6 +40,7 @@ import com.android.internal.textservice.ITextServicesSessionListener; import dalvik.system.CloseGuard; import java.util.LinkedList; +import java.util.Locale; import java.util.Queue; import java.util.concurrent.Executor; @@ -525,6 +529,161 @@ public class SpellCheckerSession { } } + /** Parameters used to create a {@link SpellCheckerSession}. */ + public static class SpellCheckerSessionParams { + @Nullable + private final Locale mLocale; + private final boolean mShouldReferToSpellCheckerLanguageSettings; + private final @SuggestionsInfo.ResultAttrs int mSupportedAttributes; + private final Bundle mExtras; + + private SpellCheckerSessionParams(Locale locale, + boolean referToSpellCheckerLanguageSettings, int supportedAttributes, + Bundle extras) { + mLocale = locale; + mShouldReferToSpellCheckerLanguageSettings = referToSpellCheckerLanguageSettings; + mSupportedAttributes = supportedAttributes; + mExtras = extras; + } + + /** + * Returns the locale in which the spell checker should operate. + * + * @see android.service.textservice.SpellCheckerService.Session#getLocale() + */ + @SuppressLint("UseIcu") + @Nullable + public Locale getLocale() { + return mLocale; + } + + /** + * Returns true if the user's spell checker language settings should be used to determine + * the spell checker locale. + */ + public boolean shouldReferToSpellCheckerLanguageSettings() { + return mShouldReferToSpellCheckerLanguageSettings; + } + + /** + * Returns a bitmask of {@link SuggestionsInfo} attributes that the spell checker can set + * in {@link SuggestionsInfo} it returns. + * + * @see android.service.textservice.SpellCheckerService.Session#getSupportedAttributes() + */ + public @SuggestionsInfo.ResultAttrs int getSupportedAttributes() { + return mSupportedAttributes; + } + + /** + * Returns a bundle containing extra parameters for the spell checker. + * + *

This bundle can be used to pass implementation-specific parameters to the + * {@link android.service.textservice.SpellCheckerService} implementation. + * + * @see android.service.textservice.SpellCheckerService.Session#getBundle() + */ + @NonNull + public Bundle getExtras() { + return mExtras; + } + + /** Builder of {@link SpellCheckerSessionParams}. */ + public static final class Builder { + @Nullable + private Locale mLocale; + private boolean mShouldReferToSpellCheckerLanguageSettings = false; + private @SuggestionsInfo.ResultAttrs int mSupportedAttributes = 0; + private Bundle mExtras = Bundle.EMPTY; + + /** Constructs a {@code Builder}. */ + public Builder() { + } + + /** + * Returns constructed {@link SpellCheckerSession} instance. + * + *

Before calling this method, either {@link #setLocale(Locale)} should be called + * with a non-null locale or + * {@link #setShouldReferToSpellCheckerLanguageSettings(boolean)} should be called with + * {@code true}. + */ + @NonNull + public SpellCheckerSessionParams build() { + if (mLocale == null && !mShouldReferToSpellCheckerLanguageSettings) { + throw new IllegalArgumentException("mLocale should not be null if " + + " mShouldReferToSpellCheckerLanguageSettings is false."); + } + return new SpellCheckerSessionParams(mLocale, + mShouldReferToSpellCheckerLanguageSettings, mSupportedAttributes, mExtras); + } + + /** + * Sets the locale in which the spell checker should operate. + * + * @see android.service.textservice.SpellCheckerService.Session#getLocale() + */ + @NonNull + public Builder setLocale(@SuppressLint("UseIcu") @Nullable Locale locale) { + mLocale = locale; + return this; + } + + /** + * Sets whether or not the user's spell checker language settings should be used to + * determine spell checker locale. + * + *

If {@code shouldReferToSpellCheckerLanguageSettings} is true, the exact way of + * determining spell checker locale differs based on {@code locale} specified in + * {@link #setLocale(Locale)}. + * If {@code shouldReferToSpellCheckerLanguageSettings} is true and {@code locale} is + * null, the locale specified in Settings will be used. If + * {@code shouldReferToSpellCheckerLanguageSettings} is true and {@code locale} is not + * null, {@link SpellCheckerSession} can be created only when the locale specified in + * Settings is the same as {@code locale}. Exceptionally, if + * {@code shouldReferToSpellCheckerLanguageSettings} is true and {@code locale} is + * language only (e.g. "en"), the specified locale in Settings (e.g. "en_US") will be + * used. + * + * @see #setLocale(Locale) + */ + @NonNull + public Builder setShouldReferToSpellCheckerLanguageSettings( + boolean shouldReferToSpellCheckerLanguageSettings) { + mShouldReferToSpellCheckerLanguageSettings = + shouldReferToSpellCheckerLanguageSettings; + return this; + } + + /** + * Sets a bitmask of {@link SuggestionsInfo} attributes that the spell checker can set + * in {@link SuggestionsInfo} it returns. + * + * @see android.service.textservice.SpellCheckerService.Session#getSupportedAttributes() + */ + @NonNull + public Builder setSupportedAttributes( + @SuggestionsInfo.ResultAttrs int supportedAttributes) { + mSupportedAttributes = supportedAttributes; + return this; + } + + /** + * Sets a bundle containing extra parameters for the spell checker. + * + *

This bundle can be used to pass implementation-specific parameters to the + * {@link android.service.textservice.SpellCheckerService} implementation. + * + * @see android.service.textservice.SpellCheckerService.Session#getBundle() + */ + @NonNull + public Builder setExtras(@NonNull Bundle extras) { + mExtras = extras; + return this; + } + } + } + /** * Callback for getting results from text services */ diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java index bf91cca855228..ae927cf60565a 100644 --- a/core/java/android/view/textservice/TextServicesManager.java +++ b/core/java/android/view/textservice/TextServicesManager.java @@ -19,7 +19,6 @@ package android.view.textservice; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.SuppressLint; import android.annotation.SystemService; import android.annotation.UserIdInt; import android.compat.annotation.UnsupportedAppUsage; @@ -35,6 +34,7 @@ import android.os.UserHandle; import android.util.Log; import android.view.inputmethod.InputMethodManager; import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener; +import android.view.textservice.SpellCheckerSession.SpellCheckerSessionParams; import com.android.internal.textservice.ISpellCheckerSessionListener; import com.android.internal.textservice.ITextServicesManager; @@ -166,15 +166,17 @@ public final class TextServicesManager { * {@link SuggestionsInfo#RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS} will be passed to the spell * checker as supported attributes. * - * @see #newSpellCheckerSession(Locale, boolean, int, Bundle, Executor, - * SpellCheckerSessionListener) - * @param bundle A bundle to pass to the spell checker. - * @param locale The locale for the spell checker. - * @param listener A spell checker session lister for getting results from the spell checker. - * The listener will be called on the calling thread. - * @param referToSpellCheckerLanguageSettings If true, the session for one of enabled - * languages in settings will be used. - * @return A spell checker session from the spell checker. + * @param locale the locale for the spell checker. If {@code locale} is null and + * referToSpellCheckerLanguageSettings is true, the locale specified in Settings will be + * returned. If {@code locale} is not null and referToSpellCheckerLanguageSettings is true, + * the locale specified in Settings will be returned only when it is same as {@code locale}. + * Exceptionally, when referToSpellCheckerLanguageSettings is true and {@code locale} is + * only language (e.g. "en"), the specified locale in Settings (e.g. "en_US") will be + * selected. + * @param listener a spell checker session lister for getting results from the spell checker. + * @param referToSpellCheckerLanguageSettings if true, the session for one of enabled + * languages in settings will be returned. + * @return a spell checker session of the spell checker */ @Nullable public SpellCheckerSession newSpellCheckerSession(@Nullable Bundle bundle, @@ -186,51 +188,40 @@ public final class TextServicesManager { int supportedAttributes = SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY | SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO | SuggestionsInfo.RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS; + SpellCheckerSessionParams.Builder paramsBuilder = new SpellCheckerSessionParams.Builder() + .setLocale(locale) + .setShouldReferToSpellCheckerLanguageSettings(referToSpellCheckerLanguageSettings) + .setSupportedAttributes(supportedAttributes); + if (bundle != null) { + paramsBuilder.setExtras(bundle); + } // Using the implicit looper to preserve the old behavior. Executor executor = new HandlerExecutor(new Handler()); - return newSpellCheckerSession(locale, referToSpellCheckerLanguageSettings, - supportedAttributes, bundle, executor, listener); + return newSpellCheckerSession(paramsBuilder.build(), executor, listener); } /** * Get a spell checker session from the spell checker. * - *

If {@code locale} is null and {@code referToSpellCheckerLanguageSettings} is true, the - * locale specified in Settings will be used. If {@code locale} is not null and - * {@code referToSpellCheckerLanguageSettings} is true, the locale specified in Settings will be - * returned only when it is same as {@code locale}. - * Exceptionally, when {@code referToSpellCheckerLanguageSettings} is true and {@code locale} is - * language only (e.g. "en"), the specified locale in Settings (e.g. "en_US") will be - * selected. - * - * @param locale The locale for the spell checker. - * @param referToSpellCheckerLanguageSettings If true, the session for one of enabled - * languages in settings will be used. - * @param supportedAttributes A union of {@link SuggestionsInfo} attributes that the spell - * checker can set in the spell checking results. - * @param bundle A bundle for passing implementation-specific extra parameters for the spell - * checker. You can check the current spell checker package by - * {@link #getCurrentSpellCheckerInfo()}. - * @param executor An executor to call the listener on. - * @param listener A spell checker session lister for getting results from a spell checker. + * @param params The parameters passed to the spell checker. + * @param executor The executor on which {@code listener} will be called back. + * @param listener a spell checker session lister for getting results from the spell checker. * @return The spell checker session of the spell checker. */ @Nullable public SpellCheckerSession newSpellCheckerSession( - @SuppressLint("UseIcu") @Nullable Locale locale, - boolean referToSpellCheckerLanguageSettings, - @SuggestionsInfo.ResultAttrs int supportedAttributes, - @Nullable Bundle bundle, + @NonNull SpellCheckerSessionParams params, @NonNull @CallbackExecutor Executor executor, @NonNull SpellCheckerSessionListener listener) { Objects.requireNonNull(executor); Objects.requireNonNull(listener); - if (!referToSpellCheckerLanguageSettings && locale == null) { + Locale locale = params.getLocale(); + if (!params.shouldReferToSpellCheckerLanguageSettings() && locale == null) { throw new IllegalArgumentException("Locale should not be null if you don't refer" + " settings."); } - if (referToSpellCheckerLanguageSettings && !isSpellCheckerEnabled()) { + if (params.shouldReferToSpellCheckerLanguageSettings() && !isSpellCheckerEnabled()) { return null; } @@ -244,7 +235,7 @@ public final class TextServicesManager { return null; } SpellCheckerSubtype subtypeInUse = null; - if (referToSpellCheckerLanguageSettings) { + if (params.shouldReferToSpellCheckerLanguageSettings()) { subtypeInUse = getCurrentSpellCheckerSubtype(true); if (subtypeInUse == null) { return null; @@ -278,7 +269,8 @@ public final class TextServicesManager { try { mService.getSpellCheckerService(mUserId, sci.getId(), subtypeInUse.getLocale(), session.getTextServicesSessionListener(), - session.getSpellCheckerSessionListener(), bundle, supportedAttributes); + session.getSpellCheckerSessionListener(), + params.getExtras(), params.getSupportedAttributes()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java index 287c18275a96b..a16c1519e4d0b 100644 --- a/core/java/android/widget/SpellChecker.java +++ b/core/java/android/widget/SpellChecker.java @@ -28,6 +28,7 @@ import android.util.Range; import android.view.textservice.SentenceSuggestionsInfo; import android.view.textservice.SpellCheckerSession; import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener; +import android.view.textservice.SpellCheckerSession.SpellCheckerSessionParams; import android.view.textservice.SuggestionsInfo; import android.view.textservice.TextInfo; import android.view.textservice.TextServicesManager; @@ -124,10 +125,12 @@ public class SpellChecker implements SpellCheckerSessionListener { | SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO | SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_GRAMMAR_ERROR | SuggestionsInfo.RESULT_ATTR_DONT_SHOW_UI_FOR_SUGGESTIONS; + SpellCheckerSessionParams params = new SpellCheckerSessionParams.Builder() + .setLocale(mCurrentLocale) + .setSupportedAttributes(supportedAttributes) + .build(); mSpellCheckerSession = mTextServicesManager.newSpellCheckerSession( - mCurrentLocale, false, supportedAttributes, - null /* Bundle not currently used by the textServicesManager */, - mTextView.getContext().getMainExecutor(), this); + params, mTextView.getContext().getMainExecutor(), this); } // Restore SpellCheckSpans in pool