Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fbf7e1f3 authored by satok's avatar satok Committed by Android (Google) Code Review
Browse files

Merge "Get rid of "isSentenceLevelSpellCheckSupported""

parents 55a28720 c7ee1b93
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -534,7 +534,7 @@ package android {
    field public static final int imeSubtypeLocale = 16843500; // 0x10102ec
    field public static final int imeSubtypeMode = 16843501; // 0x10102ed
    field public static final int immersive = 16843456; // 0x10102c0
    field public static final int importantForAccessibility = 16843699; // 0x10103b3
    field public static final int importantForAccessibility = 16843698; // 0x10103b2
    field public static final int inAnimation = 16843127; // 0x1010177
    field public static final int includeFontPadding = 16843103; // 0x101015f
    field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -936,7 +936,6 @@ package android {
    field public static final int summaryOff = 16843248; // 0x10101f0
    field public static final int summaryOn = 16843247; // 0x10101ef
    field public static final int supportsRtl = 16843688; // 0x10103a8
    field public static final int supportsSentenceSpellCheck = 16843698; // 0x10103b2
    field public static final int supportsUploading = 16843419; // 0x101029b
    field public static final int switchMinWidth = 16843632; // 0x1010370
    field public static final int switchPadding = 16843633; // 0x1010371
@@ -25520,9 +25519,8 @@ package android.view.textservice {
    method public void close();
    method public void getSentenceSuggestions(android.view.textservice.TextInfo[], int);
    method public android.view.textservice.SpellCheckerInfo getSpellChecker();
    method public void getSuggestions(android.view.textservice.TextInfo, int);
    method public void getSuggestions(android.view.textservice.TextInfo[], int, boolean);
    method public boolean isSentenceSpellCheckSupported();
    method public deprecated void getSuggestions(android.view.textservice.TextInfo, int);
    method public deprecated void getSuggestions(android.view.textservice.TextInfo[], int, boolean);
    method public boolean isSessionDisconnected();
    field public static final java.lang.String SERVICE_META_DATA = "android.view.textservice.scs";
  }
+175 −10
Original line number Diff line number Diff line
@@ -26,12 +26,18 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.text.TextUtils;
import android.text.method.WordIterator;
import android.util.Log;
import android.view.textservice.SentenceSuggestionsInfo;
import android.view.textservice.SuggestionsInfo;
import android.view.textservice.TextInfo;
import android.widget.SpellChecker;

import java.lang.ref.WeakReference;
import java.text.BreakIterator;
import java.util.ArrayList;
import java.util.Locale;

/**
 * SpellCheckerService provides an abstract base class for a spell checker.
@@ -92,6 +98,7 @@ public abstract class SpellCheckerService extends Service {
     */
    public static abstract class Session {
        private InternalISpellCheckerSession mInternalSession;
        private volatile SentenceLevelAdapter mSentenceLevelAdapter;

        /**
         * @hide
@@ -142,8 +149,8 @@ public abstract class SpellCheckerService extends Service {

        /**
         * Get sentence suggestions for specified texts in an array of TextInfo.
         * The default implementation returns an array of SentenceSuggestionsInfo by simply
         * calling onGetSuggestions.
         * The default implementation splits the input text to words and returns
         * {@link SentenceSuggestionsInfo} which contains suggestions for each word.
         * This function will run on the incoming IPC thread.
         * So, this is not called on the main thread,
         * but will be called in series on another thread.
@@ -156,14 +163,41 @@ public abstract class SpellCheckerService extends Service {
         */
        public SentenceSuggestionsInfo[] onGetSentenceSuggestionsMultiple(TextInfo[] textInfos,
                int suggestionsLimit) {
            final int length = textInfos.length;
            final SentenceSuggestionsInfo[] retval = new SentenceSuggestionsInfo[length];
            for (int i = 0; i < length; ++i) {
                final SuggestionsInfo si = onGetSuggestions(textInfos[i], suggestionsLimit);
                si.setCookieAndSequence(textInfos[i].getCookie(), textInfos[i].getSequence());
                final int N = textInfos[i].getText().length();
                retval[i] = new SentenceSuggestionsInfo(
                        new SuggestionsInfo[] {si}, new int[]{0}, new int[]{N});
            if (textInfos == null || textInfos.length == 0) {
                return SentenceLevelAdapter.EMPTY_SENTENCE_SUGGESTIONS_INFOS;
            }
            if (DBG) {
                Log.d(TAG, "onGetSentenceSuggestionsMultiple: + " + textInfos.length + ", "
                        + suggestionsLimit);
            }
            if (mSentenceLevelAdapter == null) {
                synchronized(this) {
                    if (mSentenceLevelAdapter == null) {
                        final String localeStr = getLocale();
                        if (!TextUtils.isEmpty(localeStr)) {
                            mSentenceLevelAdapter = new SentenceLevelAdapter(new Locale(localeStr));
                        }
                    }
                }
            }
            if (mSentenceLevelAdapter == null) {
                return SentenceLevelAdapter.EMPTY_SENTENCE_SUGGESTIONS_INFOS;
            }
            final int infosSize = textInfos.length;
            final SentenceSuggestionsInfo[] retval = new SentenceSuggestionsInfo[infosSize];
            for (int i = 0; i < infosSize; ++i) {
                final SentenceLevelAdapter.SentenceTextInfoParams textInfoParams =
                        mSentenceLevelAdapter.getSplitWords(textInfos[i]);
                final ArrayList<SentenceLevelAdapter.SentenceWordItem> mItems =
                        textInfoParams.mItems;
                final int itemsSize = mItems.size();
                final TextInfo[] splitTextInfos = new TextInfo[itemsSize];
                for (int j = 0; j < itemsSize; ++j) {
                    splitTextInfos[j] = mItems.get(j).mTextInfo;
                }
                retval[i] = SentenceLevelAdapter.reconstructSuggestions(
                        textInfoParams, onGetSuggestionsMultiple(
                                splitTextInfos, suggestionsLimit, true));
            }
            return retval;
        }
@@ -290,4 +324,135 @@ public abstract class SpellCheckerService extends Service {
            return internalSession;
        }
    }

    /**
     * Adapter class to accommodate word level spell checking APIs to sentence level spell checking
     * APIs used in
     * {@link SpellCheckerService.Session#onGetSuggestionsMultiple(TextInfo[], int, boolean)}
     */
    private static class SentenceLevelAdapter {
        public static final SentenceSuggestionsInfo[] EMPTY_SENTENCE_SUGGESTIONS_INFOS =
                new SentenceSuggestionsInfo[] {};
        private static final SuggestionsInfo EMPTY_SUGGESTIONS_INFO = new SuggestionsInfo(0, null);
        /**
         * Container for split TextInfo parameters
         */
        public static class SentenceWordItem {
            public final TextInfo mTextInfo;
            public final int mStart;
            public final int mLength;
            public SentenceWordItem(TextInfo ti, int start, int end) {
                mTextInfo = ti;
                mStart = start;
                mLength = end - start;
            }
        }

        /**
         * Container for originally queried TextInfo and parameters
         */
        public static class SentenceTextInfoParams {
            final TextInfo mOriginalTextInfo;
            final ArrayList<SentenceWordItem> mItems;
            final int mSize;
            public SentenceTextInfoParams(TextInfo ti, ArrayList<SentenceWordItem> items) {
                mOriginalTextInfo = ti;
                mItems = items;
                mSize = items.size();
            }
        }

        private final WordIterator mWordIterator;
        public SentenceLevelAdapter(Locale locale) {
            mWordIterator = new WordIterator(locale);
        }

        private SentenceTextInfoParams getSplitWords(TextInfo originalTextInfo) {
            final WordIterator wordIterator = mWordIterator;
            final CharSequence originalText = originalTextInfo.getText();
            final int cookie = originalTextInfo.getCookie();
            final int start = 0;
            final int end = originalText.length();
            final ArrayList<SentenceWordItem> wordItems = new ArrayList<SentenceWordItem>();
            wordIterator.setCharSequence(originalText, 0, originalText.length());
            int wordEnd = wordIterator.following(start);
            int wordStart = wordIterator.getBeginning(wordEnd);
            if (DBG) {
                Log.d(TAG, "iterator: break: ---- 1st word start = " + wordStart + ", end = "
                        + wordEnd + "\n" + originalText);
            }
            while (wordStart <= end && wordEnd != BreakIterator.DONE
                    && wordStart != BreakIterator.DONE) {
                if (wordEnd >= start && wordEnd > wordStart) {
                    final String query = originalText.subSequence(wordStart, wordEnd).toString();
                    final TextInfo ti = new TextInfo(query, cookie, query.hashCode());
                    wordItems.add(new SentenceWordItem(ti, wordStart, wordEnd));
                    if (DBG) {
                        Log.d(TAG, "Adapter: word (" + (wordItems.size() - 1) + ") " + query);
                    }
                }
                wordEnd = wordIterator.following(wordEnd);
                if (wordEnd == BreakIterator.DONE) {
                    break;
                }
                wordStart = wordIterator.getBeginning(wordEnd);
            }
            if (originalText.length() >= SpellChecker.WORD_ITERATOR_INTERVAL
                    && wordItems.size() >= 2) {
                if (DBG) {
                    Log.w(TAG, "Remove possibly divided word: "
                            + wordItems.get(0).mTextInfo.getText());
                }
                wordItems.remove(0);
            }
            return new SentenceTextInfoParams(originalTextInfo, wordItems);
        }

        public static SentenceSuggestionsInfo reconstructSuggestions(
                SentenceTextInfoParams originalTextInfoParams, SuggestionsInfo[] results) {
            if (results == null || results.length == 0) {
                return null;
            }
            if (DBG) {
                Log.w(TAG, "Adapter: onGetSuggestions: got " + results.length);
            }
            if (originalTextInfoParams == null) {
                if (DBG) {
                    Log.w(TAG, "Adapter: originalTextInfoParams is null.");
                }
                return null;
            }
            final int originalCookie = originalTextInfoParams.mOriginalTextInfo.getCookie();
            final int originalSequence =
                    originalTextInfoParams.mOriginalTextInfo.getSequence();

            final int querySize = originalTextInfoParams.mSize;
            final int[] offsets = new int[querySize];
            final int[] lengths = new int[querySize];
            final SuggestionsInfo[] reconstructedSuggestions = new SuggestionsInfo[querySize];
            for (int i = 0; i < querySize; ++i) {
                final SentenceWordItem item = originalTextInfoParams.mItems.get(i);
                SuggestionsInfo result = null;
                for (int j = 0; j < results.length; ++j) {
                    final SuggestionsInfo cur = results[j];
                    if (cur != null && cur.getSequence() == item.mTextInfo.getSequence()) {
                        result = cur;
                        result.setCookieAndSequence(originalCookie, originalSequence);
                        break;
                    }
                }
                offsets[i] = item.mStart;
                lengths[i] = item.mLength;
                reconstructedSuggestions[i] = result != null ? result : EMPTY_SUGGESTIONS_INFO;
                if (DBG) {
                    final int size = reconstructedSuggestions[i].getSuggestionsCount();
                    Log.w(TAG, "reconstructedSuggestions(" + i + ")" + size + ", first = "
                            + (size > 0 ? reconstructedSuggestions[i].getSuggestionAt(0)
                                    : "<none>") + ", offset = " + offsets[i] + ", length = "
                            + lengths[i]);
                }
            }
            return new SentenceSuggestionsInfo(reconstructedSuggestions, offsets, lengths);
        }
    }
}
+0 −13
Original line number Diff line number Diff line
@@ -45,7 +45,6 @@ public final class SpellCheckerInfo implements Parcelable {
    private final ResolveInfo mService;
    private final String mId;
    private final int mLabel;
    private final boolean mSupportsSentenceSpellCheck;

    /**
     * The spell checker setting activity's name, used by the system settings to
@@ -98,9 +97,6 @@ public final class SpellCheckerInfo implements Parcelable {
            label = sa.getResourceId(com.android.internal.R.styleable.SpellChecker_label, 0);
            settingsActivityComponent = sa.getString(
                    com.android.internal.R.styleable.SpellChecker_settingsActivity);
            mSupportsSentenceSpellCheck = sa.getBoolean(
                    com.android.internal.R.styleable.SpellChecker_supportsSentenceSpellCheck,
                    false);
            sa.recycle();

            final int depth = parser.getDepth();
@@ -142,7 +138,6 @@ public final class SpellCheckerInfo implements Parcelable {
     */
    public SpellCheckerInfo(Parcel source) {
        mLabel = source.readInt();
        mSupportsSentenceSpellCheck = source.readInt() != 0;
        mId = source.readString();
        mSettingsActivityName = source.readString();
        mService = ResolveInfo.CREATOR.createFromParcel(source);
@@ -157,13 +152,6 @@ public final class SpellCheckerInfo implements Parcelable {
        return mId;
    }

    /**
     * @hide
     */
    public boolean isSentenceSpellCheckSupported() {
        return mSupportsSentenceSpellCheck;
    }

    /**
     * Return the component of the service that implements.
     */
@@ -188,7 +176,6 @@ public final class SpellCheckerInfo implements Parcelable {
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mLabel);
        dest.writeInt(mSupportsSentenceSpellCheck ? 1 : 0);
        dest.writeString(mId);
        dest.writeString(mSettingsActivityName);
        mService.writeToParcel(dest, flags);
+5 −11
Original line number Diff line number Diff line
@@ -91,8 +91,6 @@ public class SpellCheckerSession {
     * This meta-data must reference an XML resource.
     **/
    public static final String SERVICE_META_DATA = "android.view.textservice.scs";
    private static final String SUPPORT_SENTENCE_SPELL_CHECK = "SupportSentenceSpellCheck";


    private static final int MSG_ON_GET_SUGGESTION_MULTIPLE = 1;
    private static final int MSG_ON_GET_SUGGESTION_MULTIPLE_FOR_SENTENCE = 2;
@@ -191,7 +189,9 @@ public class SpellCheckerSession {
     * Get candidate strings for a substring of the specified text.
     * @param textInfo text metadata for a spell checker
     * @param suggestionsLimit the maximum number of suggestions that will be returned
     * @deprecated use {@link SpellCheckerSession#getSentenceSuggestions(TextInfo[], int)} instead
     */
    @Deprecated
    public void getSuggestions(TextInfo textInfo, int suggestionsLimit) {
        getSuggestions(new TextInfo[] {textInfo}, suggestionsLimit, false);
    }
@@ -201,13 +201,14 @@ public class SpellCheckerSession {
     * @param textInfos an array of text metadata for a spell checker
     * @param suggestionsLimit the maximum number of suggestions that will be returned
     * @param sequentialWords true if textInfos can be treated as sequential words.
     * @deprecated use {@link SpellCheckerSession#getSentenceSuggestions(TextInfo[], int)} instead
     */
    @Deprecated
    public void getSuggestions(
            TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) {
        if (DBG) {
            Log.w(TAG, "getSuggestions from " + mSpellCheckerInfo.getId());
        }
        // TODO: Handle multiple words suggestions by using WordBreakIterator
        mSpellCheckerSessionListenerImpl.getSuggestionsMultiple(
                textInfos, suggestionsLimit, sequentialWords);
    }
@@ -281,7 +282,7 @@ public class SpellCheckerSession {
                        break;
                    case TASK_GET_SUGGESTIONS_MULTIPLE_FOR_SENTENCE:
                        if (DBG) {
                            Log.w(TAG, "Get suggestions from the spell checker.");
                            Log.w(TAG, "Get sentence suggestions from the spell checker.");
                        }
                        try {
                            session.onGetSentenceSuggestionsMultiple(
@@ -492,11 +493,4 @@ public class SpellCheckerSession {
    public ISpellCheckerSessionListener getSpellCheckerSessionListener() {
        return mSpellCheckerSessionListenerImpl;
    }

    /**
     * @return true if the spell checker supports sentence level spell checking APIs
     */
    public boolean isSentenceSpellCheckSupported() {
        return mSubtype.containsExtraValueKey(SUPPORT_SENTENCE_SPELL_CHECK);
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -116,7 +116,7 @@ public class SpellChecker implements SpellCheckerSessionListener {
                    null /* Bundle not currently used by the textServicesManager */,
                    mCurrentLocale, this,
                    false /* means any available languages from current spell checker */);
            mIsSentenceSpellCheckSupported = mSpellCheckerSession.isSentenceSpellCheckSupported();
            mIsSentenceSpellCheckSupported = true;
        }

        // Restore SpellCheckSpans in pool
Loading