Refactor sentence level spell checking APIs

Support sentence level spell checking APIs: Step 1

Change-Id: I31c0b88e7885f33a0694ab60b8f2dbceeffe42f1
This commit is contained in:
satok
2012-02-22 06:38:18 +09:00
parent 30c46ad519
commit d404fe1105
8 changed files with 178 additions and 91 deletions

View File

@@ -27,6 +27,7 @@ import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.view.textservice.SentenceSuggestionsInfo;
import android.view.textservice.SuggestionsInfo;
import android.view.textservice.TextInfo;
@@ -140,19 +141,21 @@ public abstract class SpellCheckerService extends Service {
/**
* @hide
* The default implementation returns an array of SuggestionsInfo by simply calling
* The default implementation returns an array of SentenceSuggestionsInfo by simply calling
* onGetSuggestions().
* When you override this method, make sure that suggestionsLimit is applied to suggestions
* that share the same start position and length.
*/
public SuggestionsInfo[] onGetSuggestionsMultipleForSentence(TextInfo[] textInfos,
public SentenceSuggestionsInfo[] onGetSentenceSuggestionsMultiple(TextInfo[] textInfos,
int suggestionsLimit) {
final int length = textInfos.length;
final SuggestionsInfo[] retval = new SuggestionsInfo[length];
final SentenceSuggestionsInfo[] retval = new SentenceSuggestionsInfo[length];
for (int i = 0; i < length; ++i) {
retval[i] = onGetSuggestions(textInfos[i], suggestionsLimit);
retval[i].setCookieAndSequence(
textInfos[i].getCookie(), textInfos[i].getSequence());
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});
}
return retval;
}
@@ -220,11 +223,10 @@ public abstract class SpellCheckerService extends Service {
}
@Override
public void onGetSuggestionsMultipleForSentence(
TextInfo[] textInfos, int suggestionsLimit) {
public void onGetSentenceSuggestionsMultiple(TextInfo[] textInfos, int suggestionsLimit) {
try {
mListener.onGetSuggestionsForSentence(
mSession.onGetSuggestionsMultipleForSentence(textInfos, suggestionsLimit));
mListener.onGetSentenceSuggestions(
mSession.onGetSentenceSuggestionsMultiple(textInfos, suggestionsLimit));
} catch (RemoteException e) {
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.view.textservice;
parcelable SentenceSuggestionsInfo;

View File

@@ -0,0 +1,129 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package android.view.textservice;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Arrays;
/**
* @hide
* This class contains a metadata of sentence level suggestions from the text service
*/
public final class SentenceSuggestionsInfo implements Parcelable {
private final SuggestionsInfo[] mSuggestionsInfos;
private final int[] mOffsets;
private final int[] mLengths;
/**
* Constructor.
* @param suggestionsInfos from the text service
* @param offsets the array of offsets of suggestions
* @param lengths the array of lengths of suggestions
*/
public SentenceSuggestionsInfo(
SuggestionsInfo[] suggestionsInfos, int[] offsets, int[] lengths) {
if (suggestionsInfos == null || offsets == null || lengths == null) {
throw new NullPointerException();
}
if (suggestionsInfos.length != offsets.length || offsets.length != lengths.length) {
throw new IllegalArgumentException();
}
final int infoSize = suggestionsInfos.length;
mSuggestionsInfos = Arrays.copyOf(suggestionsInfos, infoSize);
mOffsets = Arrays.copyOf(offsets, infoSize);
mLengths = Arrays.copyOf(lengths, infoSize);
}
public SentenceSuggestionsInfo(Parcel source) {
final int infoSize = source.readInt();
mSuggestionsInfos = new SuggestionsInfo[infoSize];
source.readTypedArray(mSuggestionsInfos, SuggestionsInfo.CREATOR);
mOffsets = new int[mSuggestionsInfos.length];
source.readIntArray(mOffsets);
mLengths = new int[mSuggestionsInfos.length];
source.readIntArray(mLengths);
}
/**
* Used to package this object into a {@link Parcel}.
*
* @param dest The {@link Parcel} to be written.
* @param flags The flags used for parceling.
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
final int infoSize = mSuggestionsInfos.length;
dest.writeInt(infoSize);
dest.writeTypedArray(mSuggestionsInfos, 0);
dest.writeIntArray(mOffsets);
dest.writeIntArray(mLengths);
}
@Override
public int describeContents() {
return 0;
}
/**
* @hide
*/
public SuggestionsInfo getSuggestionsInfoAt(int i) {
if (i >= 0 && i < mSuggestionsInfos.length) {
return mSuggestionsInfos[i];
}
return null;
}
/**
* @hide
*/
public int getOffsetAt(int i) {
if (i >= 0 && i < mOffsets.length) {
return mOffsets[i];
}
return -1;
}
/**
* @hide
*/
public int getLengthAt(int i) {
if (i >= 0 && i < mLengths.length) {
return mLengths[i];
}
return -1;
}
/**
* Used to make this class parcelable.
*/
public static final Parcelable.Creator<SentenceSuggestionsInfo> CREATOR
= new Parcelable.Creator<SentenceSuggestionsInfo>() {
@Override
public SentenceSuggestionsInfo createFromParcel(Parcel source) {
return new SentenceSuggestionsInfo(source);
}
@Override
public SentenceSuggestionsInfo[] newArray(int size) {
return new SentenceSuggestionsInfo[size];
}
};
}

View File

@@ -115,7 +115,7 @@ public class SpellCheckerSession {
handleOnGetSuggestionsMultiple((SuggestionsInfo[]) msg.obj);
break;
case MSG_ON_GET_SUGGESTION_MULTIPLE_FOR_SENTENCE:
handleOnGetSuggestionsMultipleForSentence((SuggestionsInfo[]) msg.obj);
handleOnGetSentenceSuggestionsMultiple((SentenceSuggestionsInfo[]) msg.obj);
break;
}
}
@@ -180,8 +180,8 @@ public class SpellCheckerSession {
/**
* @hide
*/
public void getSuggestionsForSentence(TextInfo textInfo, int suggestionsLimit) {
mSpellCheckerSessionListenerImpl.getSuggestionsMultipleForSentence(
public void getSentenceSuggestions(TextInfo textInfo, int suggestionsLimit) {
mSpellCheckerSessionListenerImpl.getSentenceSuggestionsMultiple(
new TextInfo[] {textInfo}, suggestionsLimit);
}
@@ -214,8 +214,8 @@ public class SpellCheckerSession {
mSpellCheckerSessionListener.onGetSuggestions(suggestionInfos);
}
private void handleOnGetSuggestionsMultipleForSentence(SuggestionsInfo[] suggestionInfos) {
mSpellCheckerSessionListener.onGetSuggestionsForSentence(suggestionInfos);
private void handleOnGetSentenceSuggestionsMultiple(SentenceSuggestionsInfo[] suggestionInfos) {
mSpellCheckerSessionListener.onGetSentenceSuggestions(suggestionInfos);
}
private static class SpellCheckerSessionListenerImpl extends ISpellCheckerSessionListener.Stub {
@@ -285,7 +285,7 @@ public class SpellCheckerSession {
throw new IllegalArgumentException();
}
try {
session.onGetSuggestionsMultipleForSentence(
session.onGetSentenceSuggestionsMultiple(
scp.mTextInfos, scp.mSuggestionsLimit);
} catch (RemoteException e) {
Log.e(TAG, "Failed to get suggestions " + e);
@@ -366,9 +366,9 @@ public class SpellCheckerSession {
suggestionsLimit, sequentialWords));
}
public void getSuggestionsMultipleForSentence(TextInfo[] textInfos, int suggestionsLimit) {
public void getSentenceSuggestionsMultiple(TextInfo[] textInfos, int suggestionsLimit) {
if (DBG) {
Log.w(TAG, "getSuggestionsMultipleForSentence");
Log.w(TAG, "getSentenceSuggestionsMultiple");
}
processOrEnqueueTask(
new SpellCheckerParams(TASK_GET_SUGGESTIONS_MULTIPLE_FOR_SENTENCE,
@@ -399,8 +399,8 @@ public class SpellCheckerSession {
while (!mPendingTasks.isEmpty()) {
final SpellCheckerParams tmp = mPendingTasks.poll();
if (tmp.mWhat == TASK_CLOSE) {
// Only one close task should be processed, while we need to remove all
// close tasks from the queue
// Only one close task should be processed, while we need to remove
// all close tasks from the queue
closeTask = tmp;
}
}
@@ -426,7 +426,7 @@ public class SpellCheckerSession {
}
@Override
public void onGetSuggestionsForSentence(SuggestionsInfo[] results) {
public void onGetSentenceSuggestions(SentenceSuggestionsInfo[] results) {
mHandler.sendMessage(
Message.obtain(mHandler, MSG_ON_GET_SUGGESTION_MULTIPLE_FOR_SENTENCE, results));
}
@@ -444,7 +444,7 @@ public class SpellCheckerSession {
/**
* @hide
*/
public void onGetSuggestionsForSentence(SuggestionsInfo[] results);
public void onGetSentenceSuggestions(SentenceSuggestionsInfo[] results);
}
private static class InternalListener extends ITextServicesSessionListener.Stub {

View File

@@ -21,14 +21,11 @@ import com.android.internal.util.ArrayUtils;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Arrays;
/**
* This class contains a metadata of suggestions from the text service
*/
public final class SuggestionsInfo implements Parcelable {
private static final String[] EMPTY = ArrayUtils.emptyArray(String.class);
private static final int NOT_A_LENGTH = -1;
/**
* Flag of the attributes of the suggestions that can be obtained by
@@ -50,8 +47,6 @@ public final class SuggestionsInfo implements Parcelable {
public static final int RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = 0x0004;
private final int mSuggestionsAttributes;
private final String[] mSuggestions;
private final int[] mStartPosArray;
private final int[] mLengthArray;
private final boolean mSuggestionsAvailable;
private int mCookie;
private int mSequence;
@@ -74,46 +69,12 @@ public final class SuggestionsInfo implements Parcelable {
*/
public SuggestionsInfo(
int suggestionsAttributes, String[] suggestions, int cookie, int sequence) {
this(suggestionsAttributes, suggestions, cookie, sequence, null, null);
}
/**
* @hide
* Constructor.
* @param suggestionsAttributes from the text service
* @param suggestions from the text service
* @param cookie the cookie of the input TextInfo
* @param sequence the cookie of the input TextInfo
* @param startPosArray the array of start positions of suggestions
* @param lengthArray the array of length of suggestions
*/
public SuggestionsInfo(
int suggestionsAttributes, String[] suggestions, int cookie, int sequence,
int[] startPosArray, int[] lengthArray) {
final int suggestsLen;
if (suggestions == null) {
mSuggestions = EMPTY;
mSuggestionsAvailable = false;
suggestsLen = 0;
mStartPosArray = new int[0];
mLengthArray = new int[0];
} else {
mSuggestions = suggestions;
mSuggestionsAvailable = true;
suggestsLen = suggestions.length;
if (startPosArray == null || lengthArray == null) {
mStartPosArray = new int[suggestsLen];
mLengthArray = new int[suggestsLen];
for (int i = 0; i < suggestsLen; ++i) {
mStartPosArray[i] = 0;
mLengthArray[i] = NOT_A_LENGTH;
}
} else if (suggestsLen != startPosArray.length || suggestsLen != lengthArray.length) {
throw new IllegalArgumentException();
} else {
mStartPosArray = Arrays.copyOf(startPosArray, suggestsLen);
mLengthArray = Arrays.copyOf(lengthArray, suggestsLen);
}
}
mSuggestionsAttributes = suggestionsAttributes;
mCookie = cookie;
@@ -126,10 +87,6 @@ public final class SuggestionsInfo implements Parcelable {
mCookie = source.readInt();
mSequence = source.readInt();
mSuggestionsAvailable = source.readInt() == 1;
mStartPosArray = new int[mSuggestions.length];
mLengthArray = new int[mSuggestions.length];
source.readIntArray(mStartPosArray);
source.readIntArray(mLengthArray);
}
/**
@@ -145,8 +102,6 @@ public final class SuggestionsInfo implements Parcelable {
dest.writeInt(mCookie);
dest.writeInt(mSequence);
dest.writeInt(mSuggestionsAvailable ? 1 : 0);
dest.writeIntArray(mStartPosArray);
dest.writeIntArray(mLengthArray);
}
/**
@@ -227,24 +182,4 @@ public final class SuggestionsInfo implements Parcelable {
public int describeContents() {
return 0;
}
/**
* @hide
*/
public int getSuggestionStartPosAt(int i) {
if (i >= 0 && i < mStartPosArray.length) {
return mStartPosArray[i];
}
return -1;
}
/**
* @hide
*/
public int getSuggestionLengthAt(int i) {
if (i >= 0 && i < mLengthArray.length) {
return mLengthArray[i];
}
return -1;
}
}

View File

@@ -24,6 +24,7 @@ import android.text.Spanned;
import android.text.method.WordIterator;
import android.text.style.SpellCheckSpan;
import android.text.style.SuggestionSpan;
import android.view.textservice.SentenceSuggestionsInfo;
import android.view.textservice.SpellCheckerSession;
import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener;
import android.view.textservice.SuggestionsInfo;
@@ -277,9 +278,9 @@ public class SpellChecker implements SpellCheckerSessionListener {
}
@Override
public void onGetSuggestionsForSentence(SuggestionsInfo[] results) {
public void onGetSentenceSuggestions(SentenceSuggestionsInfo[] results) {
// TODO: Handle the position and length for each suggestion
onGetSuggestions(results);
// do nothing for now
}
@Override

View File

@@ -24,7 +24,7 @@ import android.view.textservice.TextInfo;
oneway interface ISpellCheckerSession {
void onGetSuggestionsMultiple(
in TextInfo[] textInfos, int suggestionsLimit, boolean multipleWords);
void onGetSuggestionsMultipleForSentence(in TextInfo[] textInfos, int suggestionsLimit);
void onGetSentenceSuggestionsMultiple(in TextInfo[] textInfos, int suggestionsLimit);
void onCancel();
void onClose();
}

View File

@@ -16,6 +16,7 @@
package com.android.internal.textservice;
import android.view.textservice.SentenceSuggestionsInfo;
import android.view.textservice.SuggestionsInfo;
/**
@@ -23,5 +24,5 @@ import android.view.textservice.SuggestionsInfo;
*/
oneway interface ISpellCheckerSessionListener {
void onGetSuggestions(in SuggestionsInfo[] results);
void onGetSuggestionsForSentence(in SuggestionsInfo[] results);
void onGetSentenceSuggestions(in SentenceSuggestionsInfo[] result);
}