Merge "Add Executor param to TSM#newSpellCheckerSession()." into sc-dev

This commit is contained in:
TreeHugger Robot
2021-03-18 19:28:07 +00:00
committed by Android (Google) Code Review
4 changed files with 74 additions and 57 deletions

View File

@@ -52315,7 +52315,7 @@ package android.view.textservice {
method @NonNull public java.util.List<android.view.textservice.SpellCheckerInfo> 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 android.os.Bundle, @Nullable java.util.Locale, @NonNull android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener, boolean, int);
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);
}
}

View File

@@ -16,6 +16,8 @@
package android.view.textservice;
import android.annotation.BinderThread;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Build;
@@ -27,6 +29,7 @@ import android.os.RemoteException;
import android.util.Log;
import android.view.inputmethod.InputMethodManager;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.textservice.ISpellCheckerSession;
import com.android.internal.textservice.ISpellCheckerSessionListener;
import com.android.internal.textservice.ITextServicesSessionListener;
@@ -35,6 +38,7 @@ import dalvik.system.CloseGuard;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.Executor;
/**
* The SpellCheckerSession interface provides the per client functionality of SpellCheckerService.
@@ -102,38 +106,26 @@ public class SpellCheckerSession {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private final SpellCheckerSessionListener mSpellCheckerSessionListener;
private final SpellCheckerSessionListenerImpl mSpellCheckerSessionListenerImpl;
private final Executor mExecutor;
private final CloseGuard mGuard = CloseGuard.get();
/** Handler that will execute the main tasks */
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ON_GET_SUGGESTION_MULTIPLE:
handleOnGetSuggestionsMultiple((SuggestionsInfo[]) msg.obj);
break;
case MSG_ON_GET_SUGGESTION_MULTIPLE_FOR_SENTENCE:
handleOnGetSentenceSuggestionsMultiple((SentenceSuggestionsInfo[]) msg.obj);
break;
}
}
};
/**
* Constructor
* @hide
*/
public SpellCheckerSession(
SpellCheckerInfo info, TextServicesManager tsm, SpellCheckerSessionListener listener) {
SpellCheckerInfo info, TextServicesManager tsm, SpellCheckerSessionListener listener,
Executor executor) {
if (info == null || listener == null || tsm == null) {
throw new NullPointerException();
}
mSpellCheckerInfo = info;
mSpellCheckerSessionListenerImpl = new SpellCheckerSessionListenerImpl(mHandler);
mSpellCheckerSessionListenerImpl = new SpellCheckerSessionListenerImpl(this);
mInternalListener = new InternalListener(mSpellCheckerSessionListenerImpl);
mTextServicesManager = tsm;
mSpellCheckerSessionListener = listener;
mExecutor = executor;
mGuard.open("finishSession");
}
@@ -219,12 +211,13 @@ public class SpellCheckerSession {
textInfos, suggestionsLimit, sequentialWords);
}
private void handleOnGetSuggestionsMultiple(SuggestionsInfo[] suggestionInfos) {
mSpellCheckerSessionListener.onGetSuggestions(suggestionInfos);
void handleOnGetSuggestionsMultiple(SuggestionsInfo[] suggestionsInfos) {
mExecutor.execute(() -> mSpellCheckerSessionListener.onGetSuggestions(suggestionsInfos));
}
private void handleOnGetSentenceSuggestionsMultiple(SentenceSuggestionsInfo[] suggestionInfos) {
mSpellCheckerSessionListener.onGetSentenceSuggestions(suggestionInfos);
void handleOnGetSentenceSuggestionsMultiple(SentenceSuggestionsInfo[] suggestionsInfos) {
mExecutor.execute(() ->
mSpellCheckerSessionListener.onGetSentenceSuggestions(suggestionsInfos));
}
private static final class SpellCheckerSessionListenerImpl
@@ -249,7 +242,8 @@ public class SpellCheckerSession {
}
private final Queue<SpellCheckerParams> mPendingTasks = new LinkedList<>();
private Handler mHandler;
@GuardedBy("SpellCheckerSessionListenerImpl.this")
private SpellCheckerSession mSpellCheckerSession;
private static final int STATE_WAIT_CONNECTION = 0;
private static final int STATE_CONNECTED = 1;
@@ -270,8 +264,8 @@ public class SpellCheckerSession {
private HandlerThread mThread;
private Handler mAsyncHandler;
public SpellCheckerSessionListenerImpl(Handler handler) {
mHandler = handler;
SpellCheckerSessionListenerImpl(SpellCheckerSession spellCheckerSession) {
mSpellCheckerSession = spellCheckerSession;
}
private static class SpellCheckerParams {
@@ -349,6 +343,7 @@ public class SpellCheckerSession {
}
}
@GuardedBy("SpellCheckerSessionListenerImpl.this")
private void processCloseLocked() {
if (DBG) Log.d(TAG, "entering processCloseLocked:"
+ " session" + (mISpellCheckerSession != null ? ".hashCode()=#"
@@ -358,7 +353,7 @@ public class SpellCheckerSession {
if (mThread != null) {
mThread.quit();
}
mHandler = null;
mSpellCheckerSession = null;
mPendingTasks.clear();
mThread = null;
mAsyncHandler = null;
@@ -502,23 +497,30 @@ public class SpellCheckerSession {
processTask(session, scp, false);
}
@BinderThread
@Override
public void onGetSuggestions(SuggestionsInfo[] results) {
synchronized (this) {
if (mHandler != null) {
mHandler.sendMessage(Message.obtain(mHandler,
MSG_ON_GET_SUGGESTION_MULTIPLE, results));
}
SpellCheckerSession session = getSpellCheckerSession();
if (session != null) {
// Lock should not be held when calling callback, in order to avoid deadlock.
session.handleOnGetSuggestionsMultiple(results);
}
}
@BinderThread
@Override
public void onGetSentenceSuggestions(SentenceSuggestionsInfo[] results) {
synchronized (this) {
if (mHandler != null) {
mHandler.sendMessage(Message.obtain(mHandler,
MSG_ON_GET_SUGGESTION_MULTIPLE_FOR_SENTENCE, results));
}
SpellCheckerSession session = getSpellCheckerSession();
if (session != null) {
// Lock should not be held when calling callback, in order to avoid deadlock.
session.handleOnGetSentenceSuggestionsMultiple(results);
}
}
@Nullable
private SpellCheckerSession getSpellCheckerSession() {
synchronized (SpellCheckerSessionListenerImpl.this) {
return mSpellCheckerSession;
}
}
}

View File

@@ -16,6 +16,7 @@
package android.view.textservice;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
@@ -25,6 +26,8 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
@@ -40,6 +43,8 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.Executor;
/**
* System API to the overall text services, which arbitrates interaction between applications
@@ -161,10 +166,12 @@ public final class TextServicesManager {
* {@link SuggestionsInfo#RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS} will be passed to the spell
* checker as supported attributes.
*
* @see #newSpellCheckerSession(Bundle, Locale, SpellCheckerSessionListener, boolean, int)
* @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.
@@ -174,10 +181,15 @@ public final class TextServicesManager {
@Nullable Locale locale,
@NonNull SpellCheckerSessionListener listener,
boolean referToSpellCheckerLanguageSettings) {
return newSpellCheckerSession(bundle, locale, listener, referToSpellCheckerLanguageSettings,
SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY
| SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO
| SuggestionsInfo.RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS);
// Attributes existed before {@link #newSpellCheckerSession(Locale, boolean, int, Bundle,
// Executor, SpellCheckerSessionListener)} was introduced.
int supportedAttributes = SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY
| SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO
| SuggestionsInfo.RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS;
// Using the implicit looper to preserve the old behavior.
Executor executor = new HandlerExecutor(new Handler());
return newSpellCheckerSession(locale, referToSpellCheckerLanguageSettings,
supportedAttributes, bundle, executor, listener);
}
/**
@@ -191,25 +203,28 @@ public final class TextServicesManager {
* language only (e.g. "en"), the specified locale in Settings (e.g. "en_US") will be
* selected.
*
* @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 a 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.
* @return The spell checker session of the spell checker.
*/
@Nullable
public SpellCheckerSession newSpellCheckerSession(
@SuppressLint("NullableCollection") @Nullable Bundle bundle,
@SuppressLint("UseIcu") @Nullable Locale locale,
@NonNull SpellCheckerSessionListener listener,
@SuppressLint("ListenerLast") boolean referToSpellCheckerLanguageSettings,
@SuppressLint("ListenerLast") @SuggestionsInfo.ResultAttrs int supportedAttributes) {
if (listener == null) {
throw new NullPointerException();
}
boolean referToSpellCheckerLanguageSettings,
@SuggestionsInfo.ResultAttrs int supportedAttributes,
@Nullable Bundle bundle,
@NonNull @CallbackExecutor Executor executor,
@NonNull SpellCheckerSessionListener listener) {
Objects.requireNonNull(executor);
Objects.requireNonNull(listener);
if (!referToSpellCheckerLanguageSettings && locale == null) {
throw new IllegalArgumentException("Locale should not be null if you don't refer"
+ " settings.");
@@ -259,7 +274,7 @@ public final class TextServicesManager {
if (subtypeInUse == null) {
return null;
}
final SpellCheckerSession session = new SpellCheckerSession(sci, this, listener);
final SpellCheckerSession session = new SpellCheckerSession(sci, this, listener, executor);
try {
mService.getSpellCheckerService(mUserId, sci.getId(), subtypeInUse.getLocale(),
session.getTextServicesSessionListener(),

View File

@@ -126,14 +126,14 @@ public class SpellChecker implements SpellCheckerSessionListener {
|| mTextServicesManager.getCurrentSpellCheckerSubtype(true) == null) {
mSpellCheckerSession = null;
} else {
int supportedAttributes = SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY
| SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO
| SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_GRAMMAR_ERROR
| SuggestionsInfo.RESULT_ATTR_DONT_SHOW_UI_FOR_SUGGESTIONS;
mSpellCheckerSession = mTextServicesManager.newSpellCheckerSession(
mCurrentLocale, false, supportedAttributes,
null /* Bundle not currently used by the textServicesManager */,
mCurrentLocale, this,
false /* means any available languages from current spell checker */,
SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY
| SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO
| SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_GRAMMAR_ERROR
| SuggestionsInfo.RESULT_ATTR_DONT_SHOW_UI_FOR_SUGGESTIONS);
mTextView.getContext().getMainExecutor(), this);
}
// Restore SpellCheckSpans in pool