am 46a00726: Merge "Fix some compiler warnings"
* commit '46a007261fcbfbe887e22ecdf16307f95b1e4024': Fix some compiler warningsmain
commit
d94645097a
|
@ -346,7 +346,8 @@ final class KeyCodeDescriptionMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove this method once TTS supports emoticon verbalization.
|
// TODO: Remove this method once TTS supports emoticon verbalization.
|
||||||
private String getSpokenEmoticonDescription(final Context context, final String outputText) {
|
private static String getSpokenEmoticonDescription(final Context context,
|
||||||
|
final String outputText) {
|
||||||
final StringBuilder sb = new StringBuilder(SPOKEN_EMOTICON_RESOURCE_NAME_PREFIX);
|
final StringBuilder sb = new StringBuilder(SPOKEN_EMOTICON_RESOURCE_NAME_PREFIX);
|
||||||
final int textLength = outputText.length();
|
final int textLength = outputText.length();
|
||||||
for (int index = 0; index < textLength; index = outputText.offsetByCodePoints(index, 1)) {
|
for (int index = 0; index < textLength; index = outputText.offsetByCodePoints(index, 1)) {
|
||||||
|
|
|
@ -329,9 +329,8 @@ final class KeyboardAccessibilityNodeProvider<KV extends KeyboardView>
|
||||||
if (currentSettings.isWordSeparator(key.getCode())) {
|
if (currentSettings.isWordSeparator(key.getCode())) {
|
||||||
return mAccessibilityUtils.getAutoCorrectionDescription(
|
return mAccessibilityUtils.getAutoCorrectionDescription(
|
||||||
keyCodeDescription, shouldObscure);
|
keyCodeDescription, shouldObscure);
|
||||||
} else {
|
|
||||||
return keyCodeDescription;
|
|
||||||
}
|
}
|
||||||
|
return keyCodeDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -144,7 +144,7 @@ public final class CompatUtils {
|
||||||
|
|
||||||
public <T> ToObjectMethodWrapper<T> getMethod(final String name,
|
public <T> ToObjectMethodWrapper<T> getMethod(final String name,
|
||||||
final T defaultValue, final Class<?>... parameterTypes) {
|
final T defaultValue, final Class<?>... parameterTypes) {
|
||||||
return new ToObjectMethodWrapper<T>(CompatUtils.getMethod(mClass, name, parameterTypes),
|
return new ToObjectMethodWrapper<>(CompatUtils.getMethod(mClass, name, parameterTypes),
|
||||||
defaultValue);
|
defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ public class CursorAnchorInfoCompatWrapper {
|
||||||
*/
|
*/
|
||||||
public static final int FLAG_IS_RTL = 0x04;
|
public static final int FLAG_IS_RTL = 0x04;
|
||||||
|
|
||||||
private CursorAnchorInfoCompatWrapper() {
|
CursorAnchorInfoCompatWrapper() {
|
||||||
// This class is not publicly instantiable.
|
// This class is not publicly instantiable.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package com.android.inputmethod.compat;
|
package com.android.inputmethod.compat;
|
||||||
|
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
|
import android.text.Spanned;
|
||||||
import android.text.style.LocaleSpan;
|
import android.text.style.LocaleSpan;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
@ -127,13 +128,13 @@ public final class LocaleSpanCompatUtils {
|
||||||
final int spanFlag = spannable.getSpanFlags(existingLocaleSpan);
|
final int spanFlag = spannable.getSpanFlags(existingLocaleSpan);
|
||||||
if (spanStart < newStart) {
|
if (spanStart < newStart) {
|
||||||
newStart = spanStart;
|
newStart = spanStart;
|
||||||
isStartExclusive = ((spanFlag & Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) ==
|
isStartExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
if (newEnd < spanEnd) {
|
if (newEnd < spanEnd) {
|
||||||
newEnd = spanEnd;
|
newEnd = spanEnd;
|
||||||
isEndExclusive = ((spanFlag & Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) ==
|
isEndExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
existingLocaleSpansToBeMerged.add(existingLocaleSpan);
|
existingLocaleSpansToBeMerged.add(existingLocaleSpan);
|
||||||
}
|
}
|
||||||
|
@ -201,24 +202,17 @@ public final class LocaleSpanCompatUtils {
|
||||||
|
|
||||||
private static int getSpanFlag(final int originalFlag,
|
private static int getSpanFlag(final int originalFlag,
|
||||||
final boolean isStartExclusive, final boolean isEndExclusive) {
|
final boolean isStartExclusive, final boolean isEndExclusive) {
|
||||||
return (originalFlag & ~Spannable.SPAN_POINT_MARK_MASK) |
|
return (originalFlag & ~Spanned.SPAN_POINT_MARK_MASK) |
|
||||||
getSpanPointMarkFlag(isStartExclusive, isEndExclusive);
|
getSpanPointMarkFlag(isStartExclusive, isEndExclusive);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getSpanPointMarkFlag(final boolean isStartExclusive,
|
private static int getSpanPointMarkFlag(final boolean isStartExclusive,
|
||||||
final boolean isEndExclusive) {
|
final boolean isEndExclusive) {
|
||||||
if (isStartExclusive) {
|
if (isStartExclusive) {
|
||||||
if (isEndExclusive) {
|
return isEndExclusive ? Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
return Spannable.SPAN_EXCLUSIVE_EXCLUSIVE;
|
: Spanned.SPAN_EXCLUSIVE_INCLUSIVE;
|
||||||
} else {
|
|
||||||
return Spannable.SPAN_EXCLUSIVE_INCLUSIVE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (isEndExclusive) {
|
|
||||||
return Spannable.SPAN_INCLUSIVE_EXCLUSIVE;
|
|
||||||
} else {
|
|
||||||
return Spannable.SPAN_INCLUSIVE_INCLUSIVE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return isEndExclusive ? Spanned.SPAN_INCLUSIVE_EXCLUSIVE
|
||||||
|
: Spanned.SPAN_INCLUSIVE_INCLUSIVE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,13 +71,13 @@ public class NotificationCompatUtils {
|
||||||
CompatUtils.invoke(builder, null, METHOD_setPriority, PRIORITY_LOW);
|
CompatUtils.invoke(builder, null, METHOD_setPriority, PRIORITY_LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public static Notification build(final Notification.Builder builder) {
|
public static Notification build(final Notification.Builder builder) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||||
// #build was added in API level 16, JELLY_BEAN
|
// #build was added in API level 16, JELLY_BEAN
|
||||||
return (Notification) CompatUtils.invoke(builder, null, METHOD_build);
|
return (Notification) CompatUtils.invoke(builder, null, METHOD_build);
|
||||||
} else {
|
|
||||||
// #getNotification was deprecated in API level 16, JELLY_BEAN
|
|
||||||
return builder.getNotification();
|
|
||||||
}
|
}
|
||||||
|
// #getNotification was deprecated in API level 16, JELLY_BEAN
|
||||||
|
return builder.getNotification();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,19 +122,23 @@ public class ButtonSwitcher extends FrameLayout {
|
||||||
mDeleteButton.setTranslationX(STATUS_DELETE == status ? 0 : width);
|
mDeleteButton.setTranslationX(STATUS_DELETE == status ? 0 : width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The helper method for {@link AnimatorListenerAdapter}.
|
||||||
|
void animateButtonIfStatusIsEqual(final View newButton, final int newStatus) {
|
||||||
|
if (newStatus != mStatus) return;
|
||||||
|
animateButton(newButton, ANIMATION_IN);
|
||||||
|
}
|
||||||
|
|
||||||
private void animateButtonPosition(final int oldStatus, final int newStatus) {
|
private void animateButtonPosition(final int oldStatus, final int newStatus) {
|
||||||
final View oldButton = getButton(oldStatus);
|
final View oldButton = getButton(oldStatus);
|
||||||
final View newButton = getButton(newStatus);
|
final View newButton = getButton(newStatus);
|
||||||
if (null != oldButton && null != newButton) {
|
if (null != oldButton && null != newButton) {
|
||||||
// Transition between two buttons : animate out, then in
|
// Transition between two buttons : animate out, then in
|
||||||
animateButton(oldButton, ANIMATION_OUT).setListener(
|
animateButton(oldButton, ANIMATION_OUT).setListener(new AnimatorListenerAdapter() {
|
||||||
new AnimatorListenerAdapter() {
|
@Override
|
||||||
@Override
|
public void onAnimationEnd(final Animator animation) {
|
||||||
public void onAnimationEnd(final Animator animation) {
|
animateButtonIfStatusIsEqual(newButton, newStatus);
|
||||||
if (newStatus != mStatus) return;
|
}
|
||||||
animateButton(newButton, ANIMATION_IN);
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (null != oldButton) {
|
} else if (null != oldButton) {
|
||||||
animateButton(oldButton, ANIMATION_OUT);
|
animateButton(oldButton, ANIMATION_OUT);
|
||||||
} else if (null != newButton) {
|
} else if (null != newButton) {
|
||||||
|
@ -159,9 +163,8 @@ public class ButtonSwitcher extends FrameLayout {
|
||||||
if (ANIMATION_IN == direction) {
|
if (ANIMATION_IN == direction) {
|
||||||
button.setClickable(true);
|
button.setClickable(true);
|
||||||
return button.animate().translationX(0);
|
return button.animate().translationX(0);
|
||||||
} else {
|
|
||||||
button.setClickable(false);
|
|
||||||
return button.animate().translationX(outerX - innerX);
|
|
||||||
}
|
}
|
||||||
|
button.setClickable(false);
|
||||||
|
return button.animate().translationX(outerX - innerX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ public class DictionaryDownloadProgressBar extends ProgressBar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class UpdateHelper implements Runnable {
|
class UpdateHelper implements Runnable {
|
||||||
private int mProgress;
|
private int mProgress;
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
|
@ -32,7 +32,7 @@ import java.util.HashMap;
|
||||||
* in case some dictionaries appeared, disappeared, changed states etc.
|
* in case some dictionaries appeared, disappeared, changed states etc.
|
||||||
*/
|
*/
|
||||||
public class DictionaryListInterfaceState {
|
public class DictionaryListInterfaceState {
|
||||||
private static class State {
|
static class State {
|
||||||
public boolean mOpen = false;
|
public boolean mOpen = false;
|
||||||
public int mStatus = MetadataDbHelper.STATUS_UNKNOWN;
|
public int mStatus = MetadataDbHelper.STATUS_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
|
@ -255,10 +255,9 @@ public final class DictionaryProvider extends ContentProvider {
|
||||||
if (null != dictFiles && dictFiles.size() > 0) {
|
if (null != dictFiles && dictFiles.size() > 0) {
|
||||||
PrivateLog.log("Returned " + dictFiles.size() + " files");
|
PrivateLog.log("Returned " + dictFiles.size() + " files");
|
||||||
return new ResourcePathCursor(dictFiles);
|
return new ResourcePathCursor(dictFiles);
|
||||||
} else {
|
|
||||||
PrivateLog.log("No dictionary files for this URL");
|
|
||||||
return new ResourcePathCursor(Collections.<WordListInfo>emptyList());
|
|
||||||
}
|
}
|
||||||
|
PrivateLog.log("No dictionary files for this URL");
|
||||||
|
return new ResourcePathCursor(Collections.<WordListInfo>emptyList());
|
||||||
// V2_METADATA and V2_DATAFILE are not supported for query()
|
// V2_METADATA and V2_DATAFILE are not supported for query()
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
|
@ -319,14 +318,13 @@ public final class DictionaryProvider extends ContentProvider {
|
||||||
final AssetFileDescriptor afd = getContext().getResources().openRawResourceFd(
|
final AssetFileDescriptor afd = getContext().getResources().openRawResourceFd(
|
||||||
R.raw.empty);
|
R.raw.empty);
|
||||||
return afd;
|
return afd;
|
||||||
} else {
|
|
||||||
final String localFilename =
|
|
||||||
wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
|
|
||||||
final File f = getContext().getFileStreamPath(localFilename);
|
|
||||||
final ParcelFileDescriptor pfd =
|
|
||||||
ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
|
|
||||||
return new AssetFileDescriptor(pfd, 0, pfd.getStatSize());
|
|
||||||
}
|
}
|
||||||
|
final String localFilename =
|
||||||
|
wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
|
||||||
|
final File f = getContext().getFileStreamPath(localFilename);
|
||||||
|
final ParcelFileDescriptor pfd =
|
||||||
|
ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||||
|
return new AssetFileDescriptor(pfd, 0, pfd.getStatSize());
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
// No file : fall through and return null
|
// No file : fall through and return null
|
||||||
}
|
}
|
||||||
|
@ -461,13 +459,16 @@ public final class DictionaryProvider extends ContentProvider {
|
||||||
final String wordlistId = uri.getLastPathSegment();
|
final String wordlistId = uri.getLastPathSegment();
|
||||||
final String clientId = getClientId(uri);
|
final String clientId = getClientId(uri);
|
||||||
final ContentValues wordList = getWordlistMetadataForWordlistId(clientId, wordlistId);
|
final ContentValues wordList = getWordlistMetadataForWordlistId(clientId, wordlistId);
|
||||||
if (null == wordList) return 0;
|
if (null == wordList) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
final int status = wordList.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
|
final int status = wordList.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
|
||||||
final int version = wordList.getAsInteger(MetadataDbHelper.VERSION_COLUMN);
|
final int version = wordList.getAsInteger(MetadataDbHelper.VERSION_COLUMN);
|
||||||
if (MetadataDbHelper.STATUS_DELETING == status) {
|
if (MetadataDbHelper.STATUS_DELETING == status) {
|
||||||
UpdateHandler.markAsDeleted(getContext(), clientId, wordlistId, version, status);
|
UpdateHandler.markAsDeleted(getContext(), clientId, wordlistId, version, status);
|
||||||
return 1;
|
return 1;
|
||||||
} else if (MetadataDbHelper.STATUS_INSTALLED == status) {
|
}
|
||||||
|
if (MetadataDbHelper.STATUS_INSTALLED == status) {
|
||||||
final String result = uri.getQueryParameter(QUERY_PARAMETER_DELETE_RESULT);
|
final String result = uri.getQueryParameter(QUERY_PARAMETER_DELETE_RESULT);
|
||||||
if (QUERY_PARAMETER_FAILURE.equals(result)) {
|
if (QUERY_PARAMETER_FAILURE.equals(result)) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
@ -480,15 +481,10 @@ public final class DictionaryProvider extends ContentProvider {
|
||||||
wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
|
wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
|
||||||
final File f = getContext().getFileStreamPath(localFilename);
|
final File f = getContext().getFileStreamPath(localFilename);
|
||||||
// f.delete() returns true if the file was successfully deleted, false otherwise
|
// f.delete() returns true if the file was successfully deleted, false otherwise
|
||||||
if (f.delete()) {
|
return f.delete() ? 1 : 0;
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Attempt to delete a file whose status is " + status);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
Log.e(TAG, "Attempt to delete a file whose status is " + status);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -179,7 +179,7 @@ public final class DictionaryService extends Service {
|
||||||
return Service.START_REDELIVER_INTENT;
|
return Service.START_REDELIVER_INTENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void dispatchBroadcast(final Context context, final Intent intent) {
|
static void dispatchBroadcast(final Context context, final Intent intent) {
|
||||||
if (DATE_CHANGED_INTENT_ACTION.equals(intent.getAction())) {
|
if (DATE_CHANGED_INTENT_ACTION.equals(intent.getAction())) {
|
||||||
// This happens when the date of the device changes. This normally happens
|
// This happens when the date of the device changes. This normally happens
|
||||||
// at midnight local time, but it may happen if the user changes the date
|
// at midnight local time, but it may happen if the user changes the date
|
||||||
|
|
|
@ -31,7 +31,6 @@ import android.preference.Preference;
|
||||||
import android.preference.PreferenceFragment;
|
import android.preference.PreferenceFragment;
|
||||||
import android.preference.PreferenceGroup;
|
import android.preference.PreferenceGroup;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.format.DateUtils;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
|
@ -203,25 +202,19 @@ public final class DictionarySettingsFragment extends PreferenceFragment
|
||||||
@Override
|
@Override
|
||||||
public void updateCycleCompleted() {}
|
public void updateCycleCompleted() {}
|
||||||
|
|
||||||
private void refreshNetworkState() {
|
void refreshNetworkState() {
|
||||||
NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
|
NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
|
||||||
boolean isConnected = null == info ? false : info.isConnected();
|
boolean isConnected = null == info ? false : info.isConnected();
|
||||||
if (null != mUpdateNowMenu) mUpdateNowMenu.setEnabled(isConnected);
|
if (null != mUpdateNowMenu) mUpdateNowMenu.setEnabled(isConnected);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshInterface() {
|
void refreshInterface() {
|
||||||
final Activity activity = getActivity();
|
final Activity activity = getActivity();
|
||||||
if (null == activity) return;
|
if (null == activity) return;
|
||||||
final long lastUpdateDate =
|
|
||||||
MetadataDbHelper.getLastUpdateDateForClient(getActivity(), mClientId);
|
|
||||||
final PreferenceGroup prefScreen = getPreferenceScreen();
|
final PreferenceGroup prefScreen = getPreferenceScreen();
|
||||||
final Collection<? extends Preference> prefList =
|
final Collection<? extends Preference> prefList =
|
||||||
createInstalledDictSettingsCollection(mClientId);
|
createInstalledDictSettingsCollection(mClientId);
|
||||||
|
|
||||||
final String updateNowSummary = getString(R.string.last_update) + " "
|
|
||||||
+ DateUtils.formatDateTime(activity, lastUpdateDate,
|
|
||||||
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME);
|
|
||||||
|
|
||||||
activity.runOnUiThread(new Runnable() {
|
activity.runOnUiThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -239,14 +232,14 @@ public final class DictionarySettingsFragment extends PreferenceFragment
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Preference createErrorMessage(final Activity activity, final int messageResource) {
|
private static Preference createErrorMessage(final Activity activity, final int messageResource) {
|
||||||
final Preference message = new Preference(activity);
|
final Preference message = new Preference(activity);
|
||||||
message.setTitle(messageResource);
|
message.setTitle(messageResource);
|
||||||
message.setEnabled(false);
|
message.setEnabled(false);
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeAnyDictSettings(final PreferenceGroup prefGroup) {
|
static void removeAnyDictSettings(final PreferenceGroup prefGroup) {
|
||||||
for (int i = prefGroup.getPreferenceCount() - 1; i >= 0; --i) {
|
for (int i = prefGroup.getPreferenceCount() - 1; i >= 0; --i) {
|
||||||
prefGroup.removePreference(prefGroup.getPreference(i));
|
prefGroup.removePreference(prefGroup.getPreference(i));
|
||||||
}
|
}
|
||||||
|
@ -276,7 +269,7 @@ public final class DictionarySettingsFragment extends PreferenceFragment
|
||||||
.appendQueryParameter(DictionaryProvider.QUERY_PARAMETER_PROTOCOL_VERSION, "2")
|
.appendQueryParameter(DictionaryProvider.QUERY_PARAMETER_PROTOCOL_VERSION, "2")
|
||||||
.build();
|
.build();
|
||||||
final Activity activity = getActivity();
|
final Activity activity = getActivity();
|
||||||
final Cursor cursor = null == activity ? null
|
final Cursor cursor = (null == activity) ? null
|
||||||
: activity.getContentResolver().query(contentUri, null, null, null, null);
|
: activity.getContentResolver().query(contentUri, null, null, null, null);
|
||||||
|
|
||||||
if (null == cursor) {
|
if (null == cursor) {
|
||||||
|
@ -289,61 +282,57 @@ public final class DictionarySettingsFragment extends PreferenceFragment
|
||||||
final ArrayList<Preference> result = new ArrayList<>();
|
final ArrayList<Preference> result = new ArrayList<>();
|
||||||
result.add(createErrorMessage(activity, R.string.no_dictionaries_available));
|
result.add(createErrorMessage(activity, R.string.no_dictionaries_available));
|
||||||
return result;
|
return result;
|
||||||
} else {
|
|
||||||
final String systemLocaleString = Locale.getDefault().toString();
|
|
||||||
final TreeMap<String, WordListPreference> prefMap = new TreeMap<>();
|
|
||||||
final int idIndex = cursor.getColumnIndex(MetadataDbHelper.WORDLISTID_COLUMN);
|
|
||||||
final int versionIndex = cursor.getColumnIndex(MetadataDbHelper.VERSION_COLUMN);
|
|
||||||
final int localeIndex = cursor.getColumnIndex(MetadataDbHelper.LOCALE_COLUMN);
|
|
||||||
final int descriptionIndex =
|
|
||||||
cursor.getColumnIndex(MetadataDbHelper.DESCRIPTION_COLUMN);
|
|
||||||
final int statusIndex = cursor.getColumnIndex(MetadataDbHelper.STATUS_COLUMN);
|
|
||||||
final int filesizeIndex = cursor.getColumnIndex(MetadataDbHelper.FILESIZE_COLUMN);
|
|
||||||
do {
|
|
||||||
final String wordlistId = cursor.getString(idIndex);
|
|
||||||
final int version = cursor.getInt(versionIndex);
|
|
||||||
final String localeString = cursor.getString(localeIndex);
|
|
||||||
final Locale locale = new Locale(localeString);
|
|
||||||
final String description = cursor.getString(descriptionIndex);
|
|
||||||
final int status = cursor.getInt(statusIndex);
|
|
||||||
final int matchLevel =
|
|
||||||
LocaleUtils.getMatchLevel(systemLocaleString, localeString);
|
|
||||||
final String matchLevelString =
|
|
||||||
LocaleUtils.getMatchLevelSortedString(matchLevel);
|
|
||||||
final int filesize = cursor.getInt(filesizeIndex);
|
|
||||||
// The key is sorted in lexicographic order, according to the match level, then
|
|
||||||
// the description.
|
|
||||||
final String key = matchLevelString + "." + description + "." + wordlistId;
|
|
||||||
final WordListPreference existingPref = prefMap.get(key);
|
|
||||||
if (null == existingPref || existingPref.hasPriorityOver(status)) {
|
|
||||||
final WordListPreference oldPreference = mCurrentPreferenceMap.get(key);
|
|
||||||
final WordListPreference pref;
|
|
||||||
if (null != oldPreference
|
|
||||||
&& oldPreference.mVersion == version
|
|
||||||
&& oldPreference.hasStatus(status)
|
|
||||||
&& oldPreference.mLocale.equals(locale)) {
|
|
||||||
// If the old preference has all the new attributes, reuse it. Ideally,
|
|
||||||
// we should reuse the old pref even if its status is different and call
|
|
||||||
// setStatus here, but setStatus calls Preference#setSummary() which
|
|
||||||
// needs to be done on the UI thread and we're not on the UI thread
|
|
||||||
// here. We could do all this work on the UI thread, but in this case
|
|
||||||
// it's probably lighter to stay on a background thread and throw this
|
|
||||||
// old preference out.
|
|
||||||
pref = oldPreference;
|
|
||||||
} else {
|
|
||||||
// Otherwise, discard it and create a new one instead.
|
|
||||||
// TODO: when the status is different from the old one, we need to
|
|
||||||
// animate the old one out before animating the new one in.
|
|
||||||
pref = new WordListPreference(activity, mDictionaryListInterfaceState,
|
|
||||||
mClientId, wordlistId, version, locale, description, status,
|
|
||||||
filesize);
|
|
||||||
}
|
|
||||||
prefMap.put(key, pref);
|
|
||||||
}
|
|
||||||
} while (cursor.moveToNext());
|
|
||||||
mCurrentPreferenceMap = prefMap;
|
|
||||||
return prefMap.values();
|
|
||||||
}
|
}
|
||||||
|
final String systemLocaleString = Locale.getDefault().toString();
|
||||||
|
final TreeMap<String, WordListPreference> prefMap = new TreeMap<>();
|
||||||
|
final int idIndex = cursor.getColumnIndex(MetadataDbHelper.WORDLISTID_COLUMN);
|
||||||
|
final int versionIndex = cursor.getColumnIndex(MetadataDbHelper.VERSION_COLUMN);
|
||||||
|
final int localeIndex = cursor.getColumnIndex(MetadataDbHelper.LOCALE_COLUMN);
|
||||||
|
final int descriptionIndex = cursor.getColumnIndex(MetadataDbHelper.DESCRIPTION_COLUMN);
|
||||||
|
final int statusIndex = cursor.getColumnIndex(MetadataDbHelper.STATUS_COLUMN);
|
||||||
|
final int filesizeIndex = cursor.getColumnIndex(MetadataDbHelper.FILESIZE_COLUMN);
|
||||||
|
do {
|
||||||
|
final String wordlistId = cursor.getString(idIndex);
|
||||||
|
final int version = cursor.getInt(versionIndex);
|
||||||
|
final String localeString = cursor.getString(localeIndex);
|
||||||
|
final Locale locale = new Locale(localeString);
|
||||||
|
final String description = cursor.getString(descriptionIndex);
|
||||||
|
final int status = cursor.getInt(statusIndex);
|
||||||
|
final int matchLevel = LocaleUtils.getMatchLevel(systemLocaleString, localeString);
|
||||||
|
final String matchLevelString = LocaleUtils.getMatchLevelSortedString(matchLevel);
|
||||||
|
final int filesize = cursor.getInt(filesizeIndex);
|
||||||
|
// The key is sorted in lexicographic order, according to the match level, then
|
||||||
|
// the description.
|
||||||
|
final String key = matchLevelString + "." + description + "." + wordlistId;
|
||||||
|
final WordListPreference existingPref = prefMap.get(key);
|
||||||
|
if (null == existingPref || existingPref.hasPriorityOver(status)) {
|
||||||
|
final WordListPreference oldPreference = mCurrentPreferenceMap.get(key);
|
||||||
|
final WordListPreference pref;
|
||||||
|
if (null != oldPreference
|
||||||
|
&& oldPreference.mVersion == version
|
||||||
|
&& oldPreference.hasStatus(status)
|
||||||
|
&& oldPreference.mLocale.equals(locale)) {
|
||||||
|
// If the old preference has all the new attributes, reuse it. Ideally,
|
||||||
|
// we should reuse the old pref even if its status is different and call
|
||||||
|
// setStatus here, but setStatus calls Preference#setSummary() which
|
||||||
|
// needs to be done on the UI thread and we're not on the UI thread
|
||||||
|
// here. We could do all this work on the UI thread, but in this case
|
||||||
|
// it's probably lighter to stay on a background thread and throw this
|
||||||
|
// old preference out.
|
||||||
|
pref = oldPreference;
|
||||||
|
} else {
|
||||||
|
// Otherwise, discard it and create a new one instead.
|
||||||
|
// TODO: when the status is different from the old one, we need to
|
||||||
|
// animate the old one out before animating the new one in.
|
||||||
|
pref = new WordListPreference(activity, mDictionaryListInterfaceState,
|
||||||
|
mClientId, wordlistId, version, locale, description, status,
|
||||||
|
filesize);
|
||||||
|
}
|
||||||
|
prefMap.put(key, pref);
|
||||||
|
}
|
||||||
|
} while (cursor.moveToNext());
|
||||||
|
mCurrentPreferenceMap = prefMap;
|
||||||
|
return prefMap.values();
|
||||||
} finally {
|
} finally {
|
||||||
cursor.close();
|
cursor.close();
|
||||||
}
|
}
|
||||||
|
@ -396,26 +385,28 @@ public final class DictionarySettingsFragment extends PreferenceFragment
|
||||||
if (null != mUpdateNowMenu) mUpdateNowMenu.setTitle(R.string.cancel);
|
if (null != mUpdateNowMenu) mUpdateNowMenu.setTitle(R.string.cancel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopLoadingAnimation() {
|
void stopLoadingAnimation() {
|
||||||
final View preferenceView = getView();
|
final View preferenceView = getView();
|
||||||
final Activity activity = getActivity();
|
final Activity activity = getActivity();
|
||||||
if (null == activity) return;
|
if (null == activity) return;
|
||||||
|
final View loadingView = mLoadingView;
|
||||||
|
final MenuItem updateNowMenu = mUpdateNowMenu;
|
||||||
activity.runOnUiThread(new Runnable() {
|
activity.runOnUiThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mLoadingView.setVisibility(View.GONE);
|
loadingView.setVisibility(View.GONE);
|
||||||
preferenceView.setVisibility(View.VISIBLE);
|
preferenceView.setVisibility(View.VISIBLE);
|
||||||
mLoadingView.startAnimation(AnimationUtils.loadAnimation(
|
loadingView.startAnimation(AnimationUtils.loadAnimation(
|
||||||
getActivity(), android.R.anim.fade_out));
|
activity, android.R.anim.fade_out));
|
||||||
preferenceView.startAnimation(AnimationUtils.loadAnimation(
|
preferenceView.startAnimation(AnimationUtils.loadAnimation(
|
||||||
getActivity(), android.R.anim.fade_in));
|
activity, android.R.anim.fade_in));
|
||||||
// The menu is created by the framework asynchronously after the activity,
|
// The menu is created by the framework asynchronously after the activity,
|
||||||
// which means it's possible to have the activity running but the menu not
|
// which means it's possible to have the activity running but the menu not
|
||||||
// created yet - hence the necessity for a null check here.
|
// created yet - hence the necessity for a null check here.
|
||||||
if (null != mUpdateNowMenu) {
|
if (null != updateNowMenu) {
|
||||||
mUpdateNowMenu.setTitle(R.string.check_for_updates_now);
|
updateNowMenu.setTitle(R.string.check_for_updates_now);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,7 +226,7 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
|
||||||
createClientTable(db);
|
createClientTable(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addRawChecksumColumnUnlessPresent(final SQLiteDatabase db) {
|
private static void addRawChecksumColumnUnlessPresent(final SQLiteDatabase db) {
|
||||||
try {
|
try {
|
||||||
db.execSQL("SELECT " + RAW_CHECKSUM_COLUMN + " FROM "
|
db.execSQL("SELECT " + RAW_CHECKSUM_COLUMN + " FROM "
|
||||||
+ METADATA_TABLE_NAME + " LIMIT 0;");
|
+ METADATA_TABLE_NAME + " LIMIT 0;");
|
||||||
|
@ -237,7 +237,7 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addRetryCountColumnUnlessPresent(final SQLiteDatabase db) {
|
private static void addRetryCountColumnUnlessPresent(final SQLiteDatabase db) {
|
||||||
try {
|
try {
|
||||||
db.execSQL("SELECT " + RETRY_COUNT_COLUMN + " FROM "
|
db.execSQL("SELECT " + RETRY_COUNT_COLUMN + " FROM "
|
||||||
+ METADATA_TABLE_NAME + " LIMIT 0;");
|
+ METADATA_TABLE_NAME + " LIMIT 0;");
|
||||||
|
|
|
@ -30,9 +30,6 @@ import java.util.List;
|
||||||
* Helper class to easy up manipulation of dictionary pack metadata.
|
* Helper class to easy up manipulation of dictionary pack metadata.
|
||||||
*/
|
*/
|
||||||
public class MetadataHandler {
|
public class MetadataHandler {
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private static final String TAG = "DictionaryProvider:" + MetadataHandler.class.getSimpleName();
|
|
||||||
|
|
||||||
// The canonical file name for metadata. This is not the name of a real file on the
|
// The canonical file name for metadata. This is not the name of a real file on the
|
||||||
// device, but a symbolic name used in the database and in metadata handling. It is never
|
// device, but a symbolic name used in the database and in metadata handling. It is never
|
||||||
// tested against, only used for human-readability as the file name for the metadata.
|
// tested against, only used for human-readability as the file name for the metadata.
|
||||||
|
|
|
@ -43,8 +43,8 @@ public class PrivateLog {
|
||||||
+ COLUMN_DATE + " TEXT,"
|
+ COLUMN_DATE + " TEXT,"
|
||||||
+ COLUMN_EVENT + " TEXT);";
|
+ COLUMN_EVENT + " TEXT);";
|
||||||
|
|
||||||
private static final SimpleDateFormat sDateFormat =
|
static final SimpleDateFormat sDateFormat = new SimpleDateFormat(
|
||||||
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US);
|
"yyyy/MM/dd HH:mm:ss", Locale.ROOT);
|
||||||
|
|
||||||
private static PrivateLog sInstance = new PrivateLog();
|
private static PrivateLog sInstance = new PrivateLog();
|
||||||
private static DebugHelper sDebugHelper = null;
|
private static DebugHelper sDebugHelper = null;
|
||||||
|
@ -62,9 +62,9 @@ public class PrivateLog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DebugHelper extends SQLiteOpenHelper {
|
static class DebugHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
private DebugHelper(final Context context) {
|
DebugHelper(final Context context) {
|
||||||
super(context, LOG_DATABASE_NAME, null, LOG_DATABASE_VERSION);
|
super(context, LOG_DATABASE_NAME, null, LOG_DATABASE_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ public class PrivateLog {
|
||||||
insert(db, "Upgrade finished");
|
insert(db, "Upgrade finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void insert(SQLiteDatabase db, String event) {
|
static void insert(SQLiteDatabase db, String event) {
|
||||||
if (!DEBUG) return;
|
if (!DEBUG) return;
|
||||||
final ContentValues c = new ContentValues(2);
|
final ContentValues c = new ContentValues(2);
|
||||||
c.put(COLUMN_DATE, sDateFormat.format(new Date(System.currentTimeMillis())));
|
c.put(COLUMN_DATE, sDateFormat.format(new Date(System.currentTimeMillis())));
|
||||||
|
|
|
@ -59,6 +59,8 @@ import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for the update process.
|
* Handler for the update process.
|
||||||
*
|
*
|
||||||
|
@ -750,19 +752,22 @@ public final class UpdateHandler {
|
||||||
* @return an ordered list of runnables to be called to upgrade.
|
* @return an ordered list of runnables to be called to upgrade.
|
||||||
*/
|
*/
|
||||||
private static ActionBatch compareMetadataForUpgrade(final Context context,
|
private static ActionBatch compareMetadataForUpgrade(final Context context,
|
||||||
final String clientId, List<WordListMetadata> from, List<WordListMetadata> to) {
|
final String clientId, @Nullable final List<WordListMetadata> from,
|
||||||
|
@Nullable final List<WordListMetadata> to) {
|
||||||
final ActionBatch actions = new ActionBatch();
|
final ActionBatch actions = new ActionBatch();
|
||||||
// Upgrade existing word lists
|
// Upgrade existing word lists
|
||||||
DebugLogUtils.l("Comparing dictionaries");
|
DebugLogUtils.l("Comparing dictionaries");
|
||||||
final Set<String> wordListIds = new TreeSet<>();
|
final Set<String> wordListIds = new TreeSet<>();
|
||||||
// TODO: Can these be null?
|
// TODO: Can these be null?
|
||||||
if (null == from) from = new ArrayList<>();
|
final List<WordListMetadata> fromList = (from == null) ? new ArrayList<WordListMetadata>()
|
||||||
if (null == to) to = new ArrayList<>();
|
: from;
|
||||||
for (WordListMetadata wlData : from) wordListIds.add(wlData.mId);
|
final List<WordListMetadata> toList = (to == null) ? new ArrayList<WordListMetadata>()
|
||||||
for (WordListMetadata wlData : to) wordListIds.add(wlData.mId);
|
: to;
|
||||||
|
for (WordListMetadata wlData : fromList) wordListIds.add(wlData.mId);
|
||||||
|
for (WordListMetadata wlData : toList) wordListIds.add(wlData.mId);
|
||||||
for (String id : wordListIds) {
|
for (String id : wordListIds) {
|
||||||
final WordListMetadata currentInfo = MetadataHandler.findWordListById(from, id);
|
final WordListMetadata currentInfo = MetadataHandler.findWordListById(fromList, id);
|
||||||
final WordListMetadata metadataInfo = MetadataHandler.findWordListById(to, id);
|
final WordListMetadata metadataInfo = MetadataHandler.findWordListById(toList, id);
|
||||||
// TODO: Remove the following unnecessary check, since we are now doing the filtering
|
// TODO: Remove the following unnecessary check, since we are now doing the filtering
|
||||||
// inside findWordListById.
|
// inside findWordListById.
|
||||||
final WordListMetadata newInfo = null == metadataInfo
|
final WordListMetadata newInfo = null == metadataInfo
|
||||||
|
|
|
@ -38,45 +38,39 @@ import java.util.Locale;
|
||||||
* enable or delete it as appropriate for the current state of the word list.
|
* enable or delete it as appropriate for the current state of the word list.
|
||||||
*/
|
*/
|
||||||
public final class WordListPreference extends Preference {
|
public final class WordListPreference extends Preference {
|
||||||
static final private String TAG = WordListPreference.class.getSimpleName();
|
private static final String TAG = WordListPreference.class.getSimpleName();
|
||||||
|
|
||||||
// What to display in the "status" field when we receive unknown data as a status from
|
// What to display in the "status" field when we receive unknown data as a status from
|
||||||
// the content provider. Empty string sounds sensible.
|
// the content provider. Empty string sounds sensible.
|
||||||
static final private String NO_STATUS_MESSAGE = "";
|
private static final String NO_STATUS_MESSAGE = "";
|
||||||
|
|
||||||
/// Actions
|
/// Actions
|
||||||
static final private int ACTION_UNKNOWN = 0;
|
private static final int ACTION_UNKNOWN = 0;
|
||||||
static final private int ACTION_ENABLE_DICT = 1;
|
private static final int ACTION_ENABLE_DICT = 1;
|
||||||
static final private int ACTION_DISABLE_DICT = 2;
|
private static final int ACTION_DISABLE_DICT = 2;
|
||||||
static final private int ACTION_DELETE_DICT = 3;
|
private static final int ACTION_DELETE_DICT = 3;
|
||||||
|
|
||||||
// Members
|
// Members
|
||||||
// The context to get resources
|
|
||||||
final Context mContext;
|
|
||||||
// The id of the client for which this preference is.
|
|
||||||
final String mClientId;
|
|
||||||
// The metadata word list id and version of this word list.
|
// The metadata word list id and version of this word list.
|
||||||
public final String mWordlistId;
|
public final String mWordlistId;
|
||||||
public final int mVersion;
|
public final int mVersion;
|
||||||
public final Locale mLocale;
|
public final Locale mLocale;
|
||||||
public final String mDescription;
|
public final String mDescription;
|
||||||
|
|
||||||
|
// The id of the client for which this preference is.
|
||||||
|
private final String mClientId;
|
||||||
// The status
|
// The status
|
||||||
private int mStatus;
|
private int mStatus;
|
||||||
// The size of the dictionary file
|
// The size of the dictionary file
|
||||||
private final int mFilesize;
|
private final int mFilesize;
|
||||||
|
|
||||||
private final DictionaryListInterfaceState mInterfaceState;
|
private final DictionaryListInterfaceState mInterfaceState;
|
||||||
private final OnWordListPreferenceClick mPreferenceClickHandler =
|
|
||||||
new OnWordListPreferenceClick();
|
|
||||||
private final OnActionButtonClick mActionButtonClickHandler =
|
|
||||||
new OnActionButtonClick();
|
|
||||||
|
|
||||||
public WordListPreference(final Context context,
|
public WordListPreference(final Context context,
|
||||||
final DictionaryListInterfaceState dictionaryListInterfaceState, final String clientId,
|
final DictionaryListInterfaceState dictionaryListInterfaceState, final String clientId,
|
||||||
final String wordlistId, final int version, final Locale locale,
|
final String wordlistId, final int version, final Locale locale,
|
||||||
final String description, final int status, final int filesize) {
|
final String description, final int status, final int filesize) {
|
||||||
super(context, null);
|
super(context, null);
|
||||||
mContext = context;
|
|
||||||
mInterfaceState = dictionaryListInterfaceState;
|
mInterfaceState = dictionaryListInterfaceState;
|
||||||
mClientId = clientId;
|
mClientId = clientId;
|
||||||
mVersion = version;
|
mVersion = version;
|
||||||
|
@ -116,22 +110,23 @@ public final class WordListPreference extends Preference {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getSummary(final int status) {
|
private String getSummary(final int status) {
|
||||||
|
final Context context = getContext();
|
||||||
switch (status) {
|
switch (status) {
|
||||||
// If we are deleting the word list, for the user it's like it's already deleted.
|
// If we are deleting the word list, for the user it's like it's already deleted.
|
||||||
// It should be reinstallable. Exposing to the user the whole complexity of
|
// It should be reinstallable. Exposing to the user the whole complexity of
|
||||||
// the delayed deletion process between the dictionary pack and Android Keyboard
|
// the delayed deletion process between the dictionary pack and Android Keyboard
|
||||||
// would only be confusing.
|
// would only be confusing.
|
||||||
case MetadataDbHelper.STATUS_DELETING:
|
case MetadataDbHelper.STATUS_DELETING:
|
||||||
case MetadataDbHelper.STATUS_AVAILABLE:
|
case MetadataDbHelper.STATUS_AVAILABLE:
|
||||||
return mContext.getString(R.string.dictionary_available);
|
return context.getString(R.string.dictionary_available);
|
||||||
case MetadataDbHelper.STATUS_DOWNLOADING:
|
case MetadataDbHelper.STATUS_DOWNLOADING:
|
||||||
return mContext.getString(R.string.dictionary_downloading);
|
return context.getString(R.string.dictionary_downloading);
|
||||||
case MetadataDbHelper.STATUS_INSTALLED:
|
case MetadataDbHelper.STATUS_INSTALLED:
|
||||||
return mContext.getString(R.string.dictionary_installed);
|
return context.getString(R.string.dictionary_installed);
|
||||||
case MetadataDbHelper.STATUS_DISABLED:
|
case MetadataDbHelper.STATUS_DISABLED:
|
||||||
return mContext.getString(R.string.dictionary_disabled);
|
return context.getString(R.string.dictionary_disabled);
|
||||||
default:
|
default:
|
||||||
return NO_STATUS_MESSAGE;
|
return NO_STATUS_MESSAGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +149,7 @@ public final class WordListPreference extends Preference {
|
||||||
{ ButtonSwitcher.STATUS_INSTALL, ACTION_ENABLE_DICT }
|
{ ButtonSwitcher.STATUS_INSTALL, ACTION_ENABLE_DICT }
|
||||||
};
|
};
|
||||||
|
|
||||||
private int getButtonSwitcherStatus(final int status) {
|
static int getButtonSwitcherStatus(final int status) {
|
||||||
if (status >= sStatusActionList.length) {
|
if (status >= sStatusActionList.length) {
|
||||||
Log.e(TAG, "Unknown status " + status);
|
Log.e(TAG, "Unknown status " + status);
|
||||||
return ButtonSwitcher.STATUS_NO_BUTTON;
|
return ButtonSwitcher.STATUS_NO_BUTTON;
|
||||||
|
@ -162,7 +157,7 @@ public final class WordListPreference extends Preference {
|
||||||
return sStatusActionList[status][0];
|
return sStatusActionList[status][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getActionIdFromStatusAndMenuEntry(final int status) {
|
static int getActionIdFromStatusAndMenuEntry(final int status) {
|
||||||
if (status >= sStatusActionList.length) {
|
if (status >= sStatusActionList.length) {
|
||||||
Log.e(TAG, "Unknown status " + status);
|
Log.e(TAG, "Unknown status " + status);
|
||||||
return ACTION_UNKNOWN;
|
return ACTION_UNKNOWN;
|
||||||
|
@ -171,9 +166,10 @@ public final class WordListPreference extends Preference {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void disableDict() {
|
private void disableDict() {
|
||||||
SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext);
|
final Context context = getContext();
|
||||||
|
final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context);
|
||||||
CommonPreferences.disable(prefs, mWordlistId);
|
CommonPreferences.disable(prefs, mWordlistId);
|
||||||
UpdateHandler.markAsUnused(mContext, mClientId, mWordlistId, mVersion, mStatus);
|
UpdateHandler.markAsUnused(context, mClientId, mWordlistId, mVersion, mStatus);
|
||||||
if (MetadataDbHelper.STATUS_DOWNLOADING == mStatus) {
|
if (MetadataDbHelper.STATUS_DOWNLOADING == mStatus) {
|
||||||
setStatus(MetadataDbHelper.STATUS_AVAILABLE);
|
setStatus(MetadataDbHelper.STATUS_AVAILABLE);
|
||||||
} else if (MetadataDbHelper.STATUS_INSTALLED == mStatus) {
|
} else if (MetadataDbHelper.STATUS_INSTALLED == mStatus) {
|
||||||
|
@ -184,11 +180,13 @@ public final class WordListPreference extends Preference {
|
||||||
Log.e(TAG, "Unexpected state of the word list for disabling " + mStatus);
|
Log.e(TAG, "Unexpected state of the word list for disabling " + mStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableDict() {
|
private void enableDict() {
|
||||||
SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext);
|
final Context context = getContext();
|
||||||
|
final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context);
|
||||||
CommonPreferences.enable(prefs, mWordlistId);
|
CommonPreferences.enable(prefs, mWordlistId);
|
||||||
// Explicit enabling by the user : allow downloading on metered data connection.
|
// Explicit enabling by the user : allow downloading on metered data connection.
|
||||||
UpdateHandler.markAsUsed(mContext, mClientId, mWordlistId, mVersion, mStatus, true);
|
UpdateHandler.markAsUsed(context, mClientId, mWordlistId, mVersion, mStatus, true);
|
||||||
if (MetadataDbHelper.STATUS_AVAILABLE == mStatus) {
|
if (MetadataDbHelper.STATUS_AVAILABLE == mStatus) {
|
||||||
setStatus(MetadataDbHelper.STATUS_DOWNLOADING);
|
setStatus(MetadataDbHelper.STATUS_DOWNLOADING);
|
||||||
} else if (MetadataDbHelper.STATUS_DISABLED == mStatus
|
} else if (MetadataDbHelper.STATUS_DISABLED == mStatus
|
||||||
|
@ -203,11 +201,13 @@ public final class WordListPreference extends Preference {
|
||||||
Log.e(TAG, "Unexpected state of the word list for enabling " + mStatus);
|
Log.e(TAG, "Unexpected state of the word list for enabling " + mStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteDict() {
|
private void deleteDict() {
|
||||||
SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext);
|
final Context context = getContext();
|
||||||
|
final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context);
|
||||||
CommonPreferences.disable(prefs, mWordlistId);
|
CommonPreferences.disable(prefs, mWordlistId);
|
||||||
setStatus(MetadataDbHelper.STATUS_DELETING);
|
setStatus(MetadataDbHelper.STATUS_DELETING);
|
||||||
UpdateHandler.markAsDeleting(mContext, mClientId, mWordlistId, mVersion, mStatus);
|
UpdateHandler.markAsDeleting(context, mClientId, mWordlistId, mVersion, mStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -225,8 +225,8 @@ public final class WordListPreference extends Preference {
|
||||||
status.setVisibility(showProgressBar ? View.INVISIBLE : View.VISIBLE);
|
status.setVisibility(showProgressBar ? View.INVISIBLE : View.VISIBLE);
|
||||||
progressBar.setVisibility(showProgressBar ? View.VISIBLE : View.INVISIBLE);
|
progressBar.setVisibility(showProgressBar ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
|
||||||
final ButtonSwitcher buttonSwitcher =
|
final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)view.findViewById(
|
||||||
(ButtonSwitcher)view.findViewById(R.id.wordlist_button_switcher);
|
R.id.wordlist_button_switcher);
|
||||||
// We need to clear the state of the button switcher, because we reuse views; if we didn't
|
// We need to clear the state of the button switcher, because we reuse views; if we didn't
|
||||||
// reset it would animate from whatever its old state was.
|
// reset it would animate from whatever its old state was.
|
||||||
buttonSwitcher.reset(mInterfaceState);
|
buttonSwitcher.reset(mInterfaceState);
|
||||||
|
@ -244,63 +244,67 @@ public final class WordListPreference extends Preference {
|
||||||
// The button is closed.
|
// The button is closed.
|
||||||
buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON);
|
buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON);
|
||||||
}
|
}
|
||||||
buttonSwitcher.setInternalOnClickListener(mActionButtonClickHandler);
|
buttonSwitcher.setInternalOnClickListener(new View.OnClickListener() {
|
||||||
view.setOnClickListener(mPreferenceClickHandler);
|
@Override
|
||||||
|
public void onClick(final View v) {
|
||||||
|
onActionButtonClicked();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
view.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(final View v) {
|
||||||
|
onWordListClicked(v);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OnWordListPreferenceClick implements View.OnClickListener {
|
void onWordListClicked(final View v) {
|
||||||
@Override
|
// Note : v is the preference view
|
||||||
public void onClick(final View v) {
|
final ViewParent parent = v.getParent();
|
||||||
// Note : v is the preference view
|
// Just in case something changed in the framework, test for the concrete class
|
||||||
final ViewParent parent = v.getParent();
|
if (!(parent instanceof ListView)) return;
|
||||||
// Just in case something changed in the framework, test for the concrete class
|
final ListView listView = (ListView)parent;
|
||||||
if (!(parent instanceof ListView)) return;
|
final int indexToOpen;
|
||||||
final ListView listView = (ListView)parent;
|
// Close all first, we'll open back any item that needs to be open.
|
||||||
final int indexToOpen;
|
final boolean wasOpen = mInterfaceState.isOpen(mWordlistId);
|
||||||
// Close all first, we'll open back any item that needs to be open.
|
mInterfaceState.closeAll();
|
||||||
final boolean wasOpen = mInterfaceState.isOpen(mWordlistId);
|
if (wasOpen) {
|
||||||
mInterfaceState.closeAll();
|
// This button being shown. Take note that we don't want to open any button in the
|
||||||
if (wasOpen) {
|
// loop below.
|
||||||
// This button being shown. Take note that we don't want to open any button in the
|
indexToOpen = -1;
|
||||||
// loop below.
|
} else {
|
||||||
indexToOpen = -1;
|
// This button was not being shown. Open it, and remember the index of this
|
||||||
|
// child as the one to open in the following loop.
|
||||||
|
mInterfaceState.setOpen(mWordlistId, mStatus);
|
||||||
|
indexToOpen = listView.indexOfChild(v);
|
||||||
|
}
|
||||||
|
final int lastDisplayedIndex =
|
||||||
|
listView.getLastVisiblePosition() - listView.getFirstVisiblePosition();
|
||||||
|
// The "lastDisplayedIndex" is actually displayed, hence the <=
|
||||||
|
for (int i = 0; i <= lastDisplayedIndex; ++i) {
|
||||||
|
final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)listView.getChildAt(i)
|
||||||
|
.findViewById(R.id.wordlist_button_switcher);
|
||||||
|
if (i == indexToOpen) {
|
||||||
|
buttonSwitcher.setStatusAndUpdateVisuals(getButtonSwitcherStatus(mStatus));
|
||||||
} else {
|
} else {
|
||||||
// This button was not being shown. Open it, and remember the index of this
|
buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON);
|
||||||
// child as the one to open in the following loop.
|
|
||||||
mInterfaceState.setOpen(mWordlistId, mStatus);
|
|
||||||
indexToOpen = listView.indexOfChild(v);
|
|
||||||
}
|
|
||||||
final int lastDisplayedIndex =
|
|
||||||
listView.getLastVisiblePosition() - listView.getFirstVisiblePosition();
|
|
||||||
// The "lastDisplayedIndex" is actually displayed, hence the <=
|
|
||||||
for (int i = 0; i <= lastDisplayedIndex; ++i) {
|
|
||||||
final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)listView.getChildAt(i)
|
|
||||||
.findViewById(R.id.wordlist_button_switcher);
|
|
||||||
if (i == indexToOpen) {
|
|
||||||
buttonSwitcher.setStatusAndUpdateVisuals(getButtonSwitcherStatus(mStatus));
|
|
||||||
} else {
|
|
||||||
buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OnActionButtonClick implements View.OnClickListener {
|
void onActionButtonClicked() {
|
||||||
@Override
|
switch (getActionIdFromStatusAndMenuEntry(mStatus)) {
|
||||||
public void onClick(final View v) {
|
case ACTION_ENABLE_DICT:
|
||||||
switch (getActionIdFromStatusAndMenuEntry(mStatus)) {
|
enableDict();
|
||||||
case ACTION_ENABLE_DICT:
|
break;
|
||||||
enableDict();
|
case ACTION_DISABLE_DICT:
|
||||||
break;
|
disableDict();
|
||||||
case ACTION_DISABLE_DICT:
|
break;
|
||||||
disableDict();
|
case ACTION_DELETE_DICT:
|
||||||
break;
|
deleteDict();
|
||||||
case ACTION_DELETE_DICT:
|
break;
|
||||||
deleteDict();
|
default:
|
||||||
break;
|
Log.e(TAG, "Unknown menu item pressed");
|
||||||
default:
|
|
||||||
Log.e(TAG, "Unknown menu item pressed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ package com.android.inputmethod.event;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.SparseIntArray;
|
import android.util.SparseIntArray;
|
||||||
import android.view.KeyCharacterMap;
|
|
||||||
|
|
||||||
import com.android.inputmethod.latin.Constants;
|
import com.android.inputmethod.latin.Constants;
|
||||||
|
|
||||||
|
@ -70,8 +69,8 @@ public class DeadKeyCombiner implements Combiner {
|
||||||
/**
|
/**
|
||||||
* Maps Unicode combining diacritical to display-form dead key.
|
* Maps Unicode combining diacritical to display-form dead key.
|
||||||
*/
|
*/
|
||||||
private static final SparseIntArray sCombiningToAccent = new SparseIntArray();
|
static final SparseIntArray sCombiningToAccent = new SparseIntArray();
|
||||||
private static final SparseIntArray sAccentToCombining = new SparseIntArray();
|
static final SparseIntArray sAccentToCombining = new SparseIntArray();
|
||||||
static {
|
static {
|
||||||
// U+0300: COMBINING GRAVE ACCENT
|
// U+0300: COMBINING GRAVE ACCENT
|
||||||
addCombining('\u0300', ACCENT_GRAVE);
|
addCombining('\u0300', ACCENT_GRAVE);
|
||||||
|
@ -217,21 +216,20 @@ public class DeadKeyCombiner implements Combiner {
|
||||||
final StringBuilder mDeadSequence = new StringBuilder();
|
final StringBuilder mDeadSequence = new StringBuilder();
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private Event createEventChainFromSequence(final @Nonnull CharSequence text,
|
private static Event createEventChainFromSequence(final @Nonnull CharSequence text,
|
||||||
final Event originalEvent) {
|
final Event originalEvent) {
|
||||||
if (text.length() <= 0) {
|
if (text.length() <= 0) {
|
||||||
return originalEvent;
|
return originalEvent;
|
||||||
} else {
|
|
||||||
Event lastEvent = null;
|
|
||||||
int codePoint = 0;
|
|
||||||
for (int i = text.length(); i > 0; i -= Character.charCount(codePoint)) {
|
|
||||||
codePoint = Character.codePointBefore(text, i);
|
|
||||||
final Event thisEvent = Event.createHardwareKeypressEvent(codePoint,
|
|
||||||
originalEvent.mKeyCode, lastEvent, false /* isKeyRepeat */);
|
|
||||||
lastEvent = thisEvent;
|
|
||||||
}
|
|
||||||
return lastEvent;
|
|
||||||
}
|
}
|
||||||
|
Event lastEvent = null;
|
||||||
|
int codePoint = 0;
|
||||||
|
for (int i = text.length(); i > 0; i -= Character.charCount(codePoint)) {
|
||||||
|
codePoint = Character.codePointBefore(text, i);
|
||||||
|
final Event thisEvent = Event.createHardwareKeypressEvent(codePoint,
|
||||||
|
originalEvent.mKeyCode, lastEvent, false /* isKeyRepeat */);
|
||||||
|
lastEvent = thisEvent;
|
||||||
|
}
|
||||||
|
return lastEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -248,51 +246,49 @@ public class DeadKeyCombiner implements Combiner {
|
||||||
// no dead keys at all in the current input, so this combiner has nothing to do and
|
// no dead keys at all in the current input, so this combiner has nothing to do and
|
||||||
// simply returns the event as is. The majority of events will go through this path.
|
// simply returns the event as is. The majority of events will go through this path.
|
||||||
return event;
|
return event;
|
||||||
} else {
|
|
||||||
if (Character.isWhitespace(event.mCodePoint)
|
|
||||||
|| event.mCodePoint == mDeadSequence.codePointBefore(mDeadSequence.length())) {
|
|
||||||
// When whitespace or twice the same dead key, we should output the dead sequence
|
|
||||||
// as is.
|
|
||||||
final Event resultEvent = createEventChainFromSequence(mDeadSequence.toString(),
|
|
||||||
event);
|
|
||||||
mDeadSequence.setLength(0);
|
|
||||||
return resultEvent;
|
|
||||||
} else if (event.isFunctionalKeyEvent()) {
|
|
||||||
if (Constants.CODE_DELETE == event.mKeyCode) {
|
|
||||||
// Remove the last code point
|
|
||||||
final int trimIndex = mDeadSequence.length() - Character.charCount(
|
|
||||||
mDeadSequence.codePointBefore(mDeadSequence.length()));
|
|
||||||
mDeadSequence.setLength(trimIndex);
|
|
||||||
return Event.createConsumedEvent(event);
|
|
||||||
} else {
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
} else if (event.isDead()) {
|
|
||||||
mDeadSequence.appendCodePoint(event.mCodePoint);
|
|
||||||
return Event.createConsumedEvent(event);
|
|
||||||
} else {
|
|
||||||
// Combine normally.
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
sb.appendCodePoint(event.mCodePoint);
|
|
||||||
int codePointIndex = 0;
|
|
||||||
while (codePointIndex < mDeadSequence.length()) {
|
|
||||||
final int deadCodePoint = mDeadSequence.codePointAt(codePointIndex);
|
|
||||||
final char replacementSpacingChar =
|
|
||||||
Data.getNonstandardCombination(deadCodePoint, event.mCodePoint);
|
|
||||||
if (Data.NOT_A_CHAR != replacementSpacingChar) {
|
|
||||||
sb.setCharAt(0, replacementSpacingChar);
|
|
||||||
} else {
|
|
||||||
final int combining = Data.sAccentToCombining.get(deadCodePoint);
|
|
||||||
sb.appendCodePoint(0 == combining ? deadCodePoint : combining);
|
|
||||||
}
|
|
||||||
codePointIndex += Character.isSupplementaryCodePoint(deadCodePoint) ? 2 : 1;
|
|
||||||
}
|
|
||||||
final String normalizedString = Normalizer.normalize(sb, Normalizer.Form.NFC);
|
|
||||||
final Event resultEvent = createEventChainFromSequence(normalizedString, event);
|
|
||||||
mDeadSequence.setLength(0);
|
|
||||||
return resultEvent;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (Character.isWhitespace(event.mCodePoint)
|
||||||
|
|| event.mCodePoint == mDeadSequence.codePointBefore(mDeadSequence.length())) {
|
||||||
|
// When whitespace or twice the same dead key, we should output the dead sequence as is.
|
||||||
|
final Event resultEvent = createEventChainFromSequence(mDeadSequence.toString(),
|
||||||
|
event);
|
||||||
|
mDeadSequence.setLength(0);
|
||||||
|
return resultEvent;
|
||||||
|
}
|
||||||
|
if (event.isFunctionalKeyEvent()) {
|
||||||
|
if (Constants.CODE_DELETE == event.mKeyCode) {
|
||||||
|
// Remove the last code point
|
||||||
|
final int trimIndex = mDeadSequence.length() - Character.charCount(
|
||||||
|
mDeadSequence.codePointBefore(mDeadSequence.length()));
|
||||||
|
mDeadSequence.setLength(trimIndex);
|
||||||
|
return Event.createConsumedEvent(event);
|
||||||
|
}
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
if (event.isDead()) {
|
||||||
|
mDeadSequence.appendCodePoint(event.mCodePoint);
|
||||||
|
return Event.createConsumedEvent(event);
|
||||||
|
}
|
||||||
|
// Combine normally.
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
sb.appendCodePoint(event.mCodePoint);
|
||||||
|
int codePointIndex = 0;
|
||||||
|
while (codePointIndex < mDeadSequence.length()) {
|
||||||
|
final int deadCodePoint = mDeadSequence.codePointAt(codePointIndex);
|
||||||
|
final char replacementSpacingChar =
|
||||||
|
Data.getNonstandardCombination(deadCodePoint, event.mCodePoint);
|
||||||
|
if (Data.NOT_A_CHAR != replacementSpacingChar) {
|
||||||
|
sb.setCharAt(0, replacementSpacingChar);
|
||||||
|
} else {
|
||||||
|
final int combining = Data.sAccentToCombining.get(deadCodePoint);
|
||||||
|
sb.appendCodePoint(0 == combining ? deadCodePoint : combining);
|
||||||
|
}
|
||||||
|
codePointIndex += Character.isSupplementaryCodePoint(deadCodePoint) ? 2 : 1;
|
||||||
|
}
|
||||||
|
final String normalizedString = Normalizer.normalize(sb, Normalizer.Form.NFC);
|
||||||
|
final Event resultEvent = createEventChainFromSequence(normalizedString, event);
|
||||||
|
mDeadSequence.setLength(0);
|
||||||
|
return resultEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,6 +21,8 @@ import com.android.inputmethod.latin.Constants;
|
||||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||||
import com.android.inputmethod.latin.utils.StringUtils;
|
import com.android.inputmethod.latin.utils.StringUtils;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class representing a generic input event as handled by Latin IME.
|
* Class representing a generic input event as handled by Latin IME.
|
||||||
*
|
*
|
||||||
|
@ -134,12 +136,14 @@ public class Event {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public static Event createSoftwareKeypressEvent(final int codePoint, final int keyCode,
|
public static Event createSoftwareKeypressEvent(final int codePoint, final int keyCode,
|
||||||
final int x, final int y, final boolean isKeyRepeat) {
|
final int x, final int y, final boolean isKeyRepeat) {
|
||||||
return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode, x, y,
|
return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode, x, y,
|
||||||
null /* suggestedWordInfo */, isKeyRepeat ? FLAG_REPEAT : FLAG_NONE, null);
|
null /* suggestedWordInfo */, isKeyRepeat ? FLAG_REPEAT : FLAG_NONE, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public static Event createHardwareKeypressEvent(final int codePoint, final int keyCode,
|
public static Event createHardwareKeypressEvent(final int codePoint, final int keyCode,
|
||||||
final Event next, final boolean isKeyRepeat) {
|
final Event next, final boolean isKeyRepeat) {
|
||||||
return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
|
return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
|
||||||
|
@ -149,6 +153,7 @@ public class Event {
|
||||||
|
|
||||||
// This creates an input event for a dead character. @see {@link #FLAG_DEAD}
|
// This creates an input event for a dead character. @see {@link #FLAG_DEAD}
|
||||||
@ExternallyReferenced
|
@ExternallyReferenced
|
||||||
|
@Nonnull
|
||||||
public static Event createDeadEvent(final int codePoint, final int keyCode, final Event next) {
|
public static Event createDeadEvent(final int codePoint, final int keyCode, final Event next) {
|
||||||
// TODO: add an argument or something if we ever create a software layout with dead keys.
|
// TODO: add an argument or something if we ever create a software layout with dead keys.
|
||||||
return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
|
return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
|
||||||
|
@ -163,6 +168,7 @@ public class Event {
|
||||||
* @param codePoint the code point.
|
* @param codePoint the code point.
|
||||||
* @return an event for this code point.
|
* @return an event for this code point.
|
||||||
*/
|
*/
|
||||||
|
@Nonnull
|
||||||
public static Event createEventForCodePointFromUnknownSource(final int codePoint) {
|
public static Event createEventForCodePointFromUnknownSource(final int codePoint) {
|
||||||
// TODO: should we have a different type of event for this? After all, it's not a key press.
|
// TODO: should we have a different type of event for this? After all, it's not a key press.
|
||||||
return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, NOT_A_KEY_CODE,
|
return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, NOT_A_KEY_CODE,
|
||||||
|
@ -178,6 +184,7 @@ public class Event {
|
||||||
* @param y the Y coordinate.
|
* @param y the Y coordinate.
|
||||||
* @return an event for this code point and coordinates.
|
* @return an event for this code point and coordinates.
|
||||||
*/
|
*/
|
||||||
|
@Nonnull
|
||||||
public static Event createEventForCodePointFromAlreadyTypedText(final int codePoint,
|
public static Event createEventForCodePointFromAlreadyTypedText(final int codePoint,
|
||||||
final int x, final int y) {
|
final int x, final int y) {
|
||||||
// TODO: should we have a different type of event for this? After all, it's not a key press.
|
// TODO: should we have a different type of event for this? After all, it's not a key press.
|
||||||
|
@ -189,6 +196,7 @@ public class Event {
|
||||||
* Creates an input event representing the manual pick of a suggestion.
|
* Creates an input event representing the manual pick of a suggestion.
|
||||||
* @return an event for this suggestion pick.
|
* @return an event for this suggestion pick.
|
||||||
*/
|
*/
|
||||||
|
@Nonnull
|
||||||
public static Event createSuggestionPickedEvent(final SuggestedWordInfo suggestedWordInfo) {
|
public static Event createSuggestionPickedEvent(final SuggestedWordInfo suggestedWordInfo) {
|
||||||
return new Event(EVENT_TYPE_SUGGESTION_PICKED, suggestedWordInfo.mWord,
|
return new Event(EVENT_TYPE_SUGGESTION_PICKED, suggestedWordInfo.mWord,
|
||||||
NOT_A_CODE_POINT, NOT_A_KEY_CODE,
|
NOT_A_CODE_POINT, NOT_A_KEY_CODE,
|
||||||
|
@ -204,6 +212,7 @@ public class Event {
|
||||||
* @param keyCode the key code, or NOT_A_KEYCODE if not applicable.
|
* @param keyCode the key code, or NOT_A_KEYCODE if not applicable.
|
||||||
* @return an event for this text.
|
* @return an event for this text.
|
||||||
*/
|
*/
|
||||||
|
@Nonnull
|
||||||
public static Event createSoftwareTextEvent(final CharSequence text, final int keyCode) {
|
public static Event createSoftwareTextEvent(final CharSequence text, final int keyCode) {
|
||||||
return new Event(EVENT_TYPE_SOFTWARE_GENERATED_STRING, text, NOT_A_CODE_POINT, keyCode,
|
return new Event(EVENT_TYPE_SOFTWARE_GENERATED_STRING, text, NOT_A_CODE_POINT, keyCode,
|
||||||
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
|
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
|
||||||
|
@ -228,6 +237,7 @@ public class Event {
|
||||||
* @param source the event to copy the properties of.
|
* @param source the event to copy the properties of.
|
||||||
* @return an identical event marked as consumed.
|
* @return an identical event marked as consumed.
|
||||||
*/
|
*/
|
||||||
|
@Nonnull
|
||||||
public static Event createConsumedEvent(final Event source) {
|
public static Event createConsumedEvent(final Event source) {
|
||||||
// A consumed event should not input any text at all, so we pass the empty string as text.
|
// A consumed event should not input any text at all, so we pass the empty string as text.
|
||||||
return new Event(source.mEventType, source.mText, source.mCodePoint, source.mKeyCode,
|
return new Event(source.mEventType, source.mText, source.mCodePoint, source.mKeyCode,
|
||||||
|
@ -235,6 +245,7 @@ public class Event {
|
||||||
source.mNextEvent);
|
source.mNextEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public static Event createNotHandledEvent() {
|
public static Event createNotHandledEvent() {
|
||||||
return new Event(EVENT_TYPE_NOT_HANDLED, null /* text */, NOT_A_CODE_POINT, NOT_A_KEY_CODE,
|
return new Event(EVENT_TYPE_NOT_HANDLED, null /* text */, NOT_A_CODE_POINT, NOT_A_KEY_CODE,
|
||||||
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
|
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
|
||||||
|
|
|
@ -67,10 +67,9 @@ public class HardwareKeyboardEventDecoder implements HardwareEventDecoder {
|
||||||
if (keyEvent.isShiftPressed()) {
|
if (keyEvent.isShiftPressed()) {
|
||||||
return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT,
|
return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT,
|
||||||
Constants.CODE_SHIFT_ENTER, null /* next */, isKeyRepeat);
|
Constants.CODE_SHIFT_ENTER, null /* next */, isKeyRepeat);
|
||||||
} else {
|
|
||||||
return Event.createHardwareKeypressEvent(Constants.CODE_ENTER, keyCode,
|
|
||||||
null /* next */, isKeyRepeat);
|
|
||||||
}
|
}
|
||||||
|
return Event.createHardwareKeypressEvent(Constants.CODE_ENTER, keyCode,
|
||||||
|
null /* next */, isKeyRepeat);
|
||||||
}
|
}
|
||||||
// If not Enter, then this is just a regular keypress event for a normal character
|
// If not Enter, then this is just a regular keypress event for a normal character
|
||||||
// that can be committed right away, taking into account the current state.
|
// that can be committed right away, taking into account the current state.
|
||||||
|
|
|
@ -115,6 +115,7 @@ public class MyanmarReordering implements Combiner {
|
||||||
* @param newEvent the new event to add to the stream. null if none.
|
* @param newEvent the new event to add to the stream. null if none.
|
||||||
* @return the resulting software text event. Never null.
|
* @return the resulting software text event. Never null.
|
||||||
*/
|
*/
|
||||||
|
@Nonnull
|
||||||
private Event clearAndGetResultingEvent(final Event newEvent) {
|
private Event clearAndGetResultingEvent(final Event newEvent) {
|
||||||
final CharSequence combinedText;
|
final CharSequence combinedText;
|
||||||
if (mCurrentEvents.size() > 0) {
|
if (mCurrentEvents.size() > 0) {
|
||||||
|
@ -139,7 +140,8 @@ public class MyanmarReordering implements Combiner {
|
||||||
if (null == lastEvent) {
|
if (null == lastEvent) {
|
||||||
mCurrentEvents.add(newEvent);
|
mCurrentEvents.add(newEvent);
|
||||||
return Event.createConsumedEvent(newEvent);
|
return Event.createConsumedEvent(newEvent);
|
||||||
} else if (isConsonantOrMedial(lastEvent.mCodePoint)) {
|
}
|
||||||
|
if (isConsonantOrMedial(lastEvent.mCodePoint)) {
|
||||||
final Event resultingEvent = clearAndGetResultingEvent(null);
|
final Event resultingEvent = clearAndGetResultingEvent(null);
|
||||||
mCurrentEvents.add(Event.createSoftwareKeypressEvent(ZERO_WIDTH_NON_JOINER,
|
mCurrentEvents.add(Event.createSoftwareKeypressEvent(ZERO_WIDTH_NON_JOINER,
|
||||||
Event.NOT_A_KEY_CODE,
|
Event.NOT_A_KEY_CODE,
|
||||||
|
@ -147,15 +149,17 @@ public class MyanmarReordering implements Combiner {
|
||||||
false /* isKeyRepeat */));
|
false /* isKeyRepeat */));
|
||||||
mCurrentEvents.add(newEvent);
|
mCurrentEvents.add(newEvent);
|
||||||
return resultingEvent;
|
return resultingEvent;
|
||||||
} else { // VOWEL_E == lastCodePoint. But if that was anything else this is correct too.
|
|
||||||
return clearAndGetResultingEvent(newEvent);
|
|
||||||
}
|
}
|
||||||
} if (isConsonant(codePoint)) {
|
// VOWEL_E == lastCodePoint. But if that was anything else this is correct too.
|
||||||
|
return clearAndGetResultingEvent(newEvent);
|
||||||
|
}
|
||||||
|
if (isConsonant(codePoint)) {
|
||||||
final Event lastEvent = getLastEvent();
|
final Event lastEvent = getLastEvent();
|
||||||
if (null == lastEvent) {
|
if (null == lastEvent) {
|
||||||
mCurrentEvents.add(newEvent);
|
mCurrentEvents.add(newEvent);
|
||||||
return Event.createConsumedEvent(newEvent);
|
return Event.createConsumedEvent(newEvent);
|
||||||
} else if (VOWEL_E == lastEvent.mCodePoint) {
|
}
|
||||||
|
if (VOWEL_E == lastEvent.mCodePoint) {
|
||||||
final int eventSize = mCurrentEvents.size();
|
final int eventSize = mCurrentEvents.size();
|
||||||
if (eventSize >= 2
|
if (eventSize >= 2
|
||||||
&& mCurrentEvents.get(eventSize - 2).mCodePoint == ZERO_WIDTH_NON_JOINER) {
|
&& mCurrentEvents.get(eventSize - 2).mCodePoint == ZERO_WIDTH_NON_JOINER) {
|
||||||
|
@ -178,15 +182,17 @@ public class MyanmarReordering implements Combiner {
|
||||||
mCurrentEvents.add(newEvent);
|
mCurrentEvents.add(newEvent);
|
||||||
mCurrentEvents.add(lastEvent);
|
mCurrentEvents.add(lastEvent);
|
||||||
return Event.createConsumedEvent(newEvent);
|
return Event.createConsumedEvent(newEvent);
|
||||||
} else { // lastCodePoint is a consonant/medial. But if it's something else it's fine
|
|
||||||
return clearAndGetResultingEvent(newEvent);
|
|
||||||
}
|
}
|
||||||
} else if (isMedial(codePoint)) {
|
// lastCodePoint is a consonant/medial. But if it's something else it's fine
|
||||||
|
return clearAndGetResultingEvent(newEvent);
|
||||||
|
}
|
||||||
|
if (isMedial(codePoint)) {
|
||||||
final Event lastEvent = getLastEvent();
|
final Event lastEvent = getLastEvent();
|
||||||
if (null == lastEvent) {
|
if (null == lastEvent) {
|
||||||
mCurrentEvents.add(newEvent);
|
mCurrentEvents.add(newEvent);
|
||||||
return Event.createConsumedEvent(newEvent);
|
return Event.createConsumedEvent(newEvent);
|
||||||
} else if (VOWEL_E == lastEvent.mCodePoint) {
|
}
|
||||||
|
if (VOWEL_E == lastEvent.mCodePoint) {
|
||||||
final int eventSize = mCurrentEvents.size();
|
final int eventSize = mCurrentEvents.size();
|
||||||
// If there is already a consonant, then we are in the middle of a syllable, and we
|
// If there is already a consonant, then we are in the middle of a syllable, and we
|
||||||
// need to reorder.
|
// need to reorder.
|
||||||
|
@ -205,37 +211,36 @@ public class MyanmarReordering implements Combiner {
|
||||||
}
|
}
|
||||||
// Otherwise, we just commit everything.
|
// Otherwise, we just commit everything.
|
||||||
return clearAndGetResultingEvent(null);
|
return clearAndGetResultingEvent(null);
|
||||||
} else { // lastCodePoint is a consonant/medial. But if it's something else it's fine
|
|
||||||
return clearAndGetResultingEvent(newEvent);
|
|
||||||
}
|
}
|
||||||
} else if (Constants.CODE_DELETE == newEvent.mKeyCode) {
|
// lastCodePoint is a consonant/medial. But if it's something else it's fine
|
||||||
final Event lastEvent = getLastEvent();
|
return clearAndGetResultingEvent(newEvent);
|
||||||
|
}
|
||||||
|
final Event lastEvent = getLastEvent();
|
||||||
|
if (Constants.CODE_DELETE == newEvent.mKeyCode && null != lastEvent) {
|
||||||
final int eventSize = mCurrentEvents.size();
|
final int eventSize = mCurrentEvents.size();
|
||||||
if (null != lastEvent) {
|
if (VOWEL_E == lastEvent.mCodePoint) {
|
||||||
if (VOWEL_E == lastEvent.mCodePoint) {
|
// We have a VOWEL_E at the end. There are four cases.
|
||||||
// We have a VOWEL_E at the end. There are four cases.
|
// - The vowel is the only code point in the buffer. Remove it.
|
||||||
// - The vowel is the only code point in the buffer. Remove it.
|
// - The vowel is preceded by a ZWNJ. Remove both vowel E and ZWNJ.
|
||||||
// - The vowel is preceded by a ZWNJ. Remove both vowel E and ZWNJ.
|
// - The vowel is preceded by a consonant/medial, remove the consonant/medial.
|
||||||
// - The vowel is preceded by a consonant/medial, remove the consonant/medial.
|
// - In all other cases, it's strange, so just remove the last code point.
|
||||||
// - In all other cases, it's strange, so just remove the last code point.
|
if (eventSize <= 1) {
|
||||||
if (eventSize <= 1) {
|
mCurrentEvents.clear();
|
||||||
mCurrentEvents.clear();
|
} else { // eventSize >= 2
|
||||||
} else { // eventSize >= 2
|
final int previousCodePoint = mCurrentEvents.get(eventSize - 2).mCodePoint;
|
||||||
final int previousCodePoint = mCurrentEvents.get(eventSize - 2).mCodePoint;
|
if (previousCodePoint == ZERO_WIDTH_NON_JOINER) {
|
||||||
if (previousCodePoint == ZERO_WIDTH_NON_JOINER) {
|
mCurrentEvents.remove(eventSize - 1);
|
||||||
mCurrentEvents.remove(eventSize - 1);
|
mCurrentEvents.remove(eventSize - 2);
|
||||||
mCurrentEvents.remove(eventSize - 2);
|
} else if (isConsonantOrMedial(previousCodePoint)) {
|
||||||
} else if (isConsonantOrMedial(previousCodePoint)) {
|
mCurrentEvents.remove(eventSize - 2);
|
||||||
mCurrentEvents.remove(eventSize - 2);
|
} else {
|
||||||
} else {
|
mCurrentEvents.remove(eventSize - 1);
|
||||||
mCurrentEvents.remove(eventSize - 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Event.createConsumedEvent(newEvent);
|
|
||||||
} else if (eventSize > 0) {
|
|
||||||
mCurrentEvents.remove(eventSize - 1);
|
|
||||||
return Event.createConsumedEvent(newEvent);
|
|
||||||
}
|
}
|
||||||
|
return Event.createConsumedEvent(newEvent);
|
||||||
|
} else if (eventSize > 0) {
|
||||||
|
mCurrentEvents.remove(eventSize - 1);
|
||||||
|
return Event.createConsumedEvent(newEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// This character is not part of the combining scheme, so we should reset everything.
|
// This character is not part of the combining scheme, so we should reset everything.
|
||||||
|
@ -243,10 +248,9 @@ public class MyanmarReordering implements Combiner {
|
||||||
// If we have events in flight, then add the new event and return the resulting event.
|
// If we have events in flight, then add the new event and return the resulting event.
|
||||||
mCurrentEvents.add(newEvent);
|
mCurrentEvents.add(newEvent);
|
||||||
return clearAndGetResultingEvent(null);
|
return clearAndGetResultingEvent(null);
|
||||||
} else {
|
|
||||||
// If we don't have any events in flight, then just pass this one through.
|
|
||||||
return newEvent;
|
|
||||||
}
|
}
|
||||||
|
// If we don't have any events in flight, then just pass this one through.
|
||||||
|
return newEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -25,7 +25,6 @@ import android.view.inputmethod.EditorInfo;
|
||||||
import com.android.inputmethod.compat.EditorInfoCompatUtils;
|
import com.android.inputmethod.compat.EditorInfoCompatUtils;
|
||||||
import com.android.inputmethod.latin.RichInputMethodSubtype;
|
import com.android.inputmethod.latin.RichInputMethodSubtype;
|
||||||
import com.android.inputmethod.latin.utils.InputTypeUtils;
|
import com.android.inputmethod.latin.utils.InputTypeUtils;
|
||||||
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
|
@ -40,7 +40,6 @@ import com.android.inputmethod.latin.R;
|
||||||
import com.android.inputmethod.latin.RichInputMethodSubtype;
|
import com.android.inputmethod.latin.RichInputMethodSubtype;
|
||||||
import com.android.inputmethod.latin.SubtypeSwitcher;
|
import com.android.inputmethod.latin.SubtypeSwitcher;
|
||||||
import com.android.inputmethod.latin.define.DebugFlags;
|
import com.android.inputmethod.latin.define.DebugFlags;
|
||||||
import com.android.inputmethod.latin.utils.DebugLogUtils;
|
|
||||||
import com.android.inputmethod.latin.utils.InputTypeUtils;
|
import com.android.inputmethod.latin.utils.InputTypeUtils;
|
||||||
import com.android.inputmethod.latin.utils.ScriptUtils;
|
import com.android.inputmethod.latin.utils.ScriptUtils;
|
||||||
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
||||||
|
@ -424,9 +423,8 @@ public final class KeyboardLayoutSet {
|
||||||
final String tag = parser.getName();
|
final String tag = parser.getName();
|
||||||
if (TAG_KEYBOARD_SET.equals(tag)) {
|
if (TAG_KEYBOARD_SET.equals(tag)) {
|
||||||
break;
|
break;
|
||||||
} else {
|
|
||||||
throw new XmlParseUtils.IllegalEndTag(parser, tag, TAG_KEYBOARD_SET);
|
|
||||||
}
|
}
|
||||||
|
throw new XmlParseUtils.IllegalEndTag(parser, tag, TAG_KEYBOARD_SET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,6 +273,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Future method for requesting an updating to the shift state.
|
// Future method for requesting an updating to the shift state.
|
||||||
|
@Override
|
||||||
public void requestUpdatingShiftState(final int currentAutoCapsState,
|
public void requestUpdatingShiftState(final int currentAutoCapsState,
|
||||||
final int currentRecapitalizeState) {
|
final int currentRecapitalizeState) {
|
||||||
mState.onUpdateShiftState(currentAutoCapsState, currentRecapitalizeState);
|
mState.onUpdateShiftState(currentAutoCapsState, currentRecapitalizeState);
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package com.android.inputmethod.keyboard;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.inputmethod.keyboard.internal.TouchPositionCorrection;
|
import com.android.inputmethod.keyboard.internal.TouchPositionCorrection;
|
||||||
|
|
|
@ -181,7 +181,7 @@ public class TextDecorator {
|
||||||
layoutMain();
|
layoutMain();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void layoutMain() {
|
void layoutMain() {
|
||||||
final CursorAnchorInfoCompatWrapper info = mCursorAnchorInfoWrapper;
|
final CursorAnchorInfoCompatWrapper info = mCursorAnchorInfoWrapper;
|
||||||
|
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
|
@ -289,7 +289,7 @@ public class TextDecorator {
|
||||||
mHasRtlCharsInLastComposingText);
|
mHasRtlCharsInLastComposingText);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onClickIndicator() {
|
void onClickIndicator() {
|
||||||
if (mMode != MODE_SHOWING_INDICATOR) {
|
if (mMode != MODE_SHOWING_INDICATOR) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,7 +147,7 @@ final class EmojiCategory {
|
||||||
mShownCategories.add(properties);
|
mShownCategories.add(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCategoryName(final int categoryId, final int categoryPageId) {
|
public static String getCategoryName(final int categoryId, final int categoryPageId) {
|
||||||
return sCategoryName[categoryId] + "-" + categoryPageId;
|
return sCategoryName[categoryId] + "-" + categoryPageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,6 +138,21 @@ final class EmojiPageKeyboardView extends KeyboardView implements
|
||||||
return mKeyDetector.detectHitKey(x, y);
|
return mKeyDetector.detectHitKey(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void callListenerOnReleaseKey(final Key releasedKey, final boolean withKeyRegistering) {
|
||||||
|
releasedKey.onReleased();
|
||||||
|
invalidateKey(releasedKey);
|
||||||
|
if (withKeyRegistering) {
|
||||||
|
mListener.onReleaseKey(releasedKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void callListenerOnPressKey(final Key pressedKey) {
|
||||||
|
mPendingKeyDown = null;
|
||||||
|
pressedKey.onReleased();
|
||||||
|
invalidateKey(pressedKey);
|
||||||
|
mListener.onPressKey(pressedKey);
|
||||||
|
}
|
||||||
|
|
||||||
public void releaseCurrentKey(final boolean withKeyRegistering) {
|
public void releaseCurrentKey(final boolean withKeyRegistering) {
|
||||||
mHandler.removeCallbacks(mPendingKeyDown);
|
mHandler.removeCallbacks(mPendingKeyDown);
|
||||||
mPendingKeyDown = null;
|
mPendingKeyDown = null;
|
||||||
|
@ -145,11 +160,7 @@ final class EmojiPageKeyboardView extends KeyboardView implements
|
||||||
if (currentKey == null) {
|
if (currentKey == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
currentKey.onReleased();
|
callListenerOnReleaseKey(currentKey, withKeyRegistering);
|
||||||
invalidateKey(currentKey);
|
|
||||||
if (withKeyRegistering) {
|
|
||||||
mListener.onReleaseKey(currentKey);
|
|
||||||
}
|
|
||||||
mCurrentKey = null;
|
mCurrentKey = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,10 +176,7 @@ final class EmojiPageKeyboardView extends KeyboardView implements
|
||||||
mPendingKeyDown = new Runnable() {
|
mPendingKeyDown = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mPendingKeyDown = null;
|
callListenerOnPressKey(key);
|
||||||
key.onPressed();
|
|
||||||
invalidateKey(key);
|
|
||||||
mListener.onPressKey(key);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mHandler.postDelayed(mPendingKeyDown, KEY_PRESS_DELAY_TIME);
|
mHandler.postDelayed(mPendingKeyDown, KEY_PRESS_DELAY_TIME);
|
||||||
|
@ -195,15 +203,11 @@ final class EmojiPageKeyboardView extends KeyboardView implements
|
||||||
mHandler.postDelayed(new Runnable() {
|
mHandler.postDelayed(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
key.onReleased();
|
callListenerOnReleaseKey(key, true /* withRegistering */);
|
||||||
invalidateKey(key);
|
|
||||||
mListener.onReleaseKey(key);
|
|
||||||
}
|
}
|
||||||
}, KEY_RELEASE_DELAY_TIME);
|
}, KEY_RELEASE_DELAY_TIME);
|
||||||
} else {
|
} else {
|
||||||
key.onReleased();
|
callListenerOnReleaseKey(key, true /* withRegistering */);
|
||||||
invalidateKey(key);
|
|
||||||
mListener.onReleaseKey(key);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addTab(final TabHost host, final int categoryId) {
|
private void addTab(final TabHost host, final int categoryId) {
|
||||||
final String tabId = mEmojiCategory.getCategoryName(categoryId, 0 /* categoryPageId */);
|
final String tabId = EmojiCategory.getCategoryName(categoryId, 0 /* categoryPageId */);
|
||||||
final TabHost.TabSpec tspec = host.newTabSpec(tabId);
|
final TabHost.TabSpec tspec = host.newTabSpec(tabId);
|
||||||
tspec.setContent(R.id.emoji_keyboard_dummy);
|
tspec.setContent(R.id.emoji_keyboard_dummy);
|
||||||
final ImageView iconView = (ImageView)LayoutInflater.from(getContext()).inflate(
|
final ImageView iconView = (ImageView)LayoutInflater.from(getContext()).inflate(
|
||||||
|
|
|
@ -148,7 +148,7 @@ public final class KeyPreviewChoreographer {
|
||||||
keyPreviewView.setPivotY(previewHeight);
|
keyPreviewView.setPivotY(previewHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showKeyPreview(final Key key, final KeyPreviewView keyPreviewView,
|
void showKeyPreview(final Key key, final KeyPreviewView keyPreviewView,
|
||||||
final boolean withAnimation) {
|
final boolean withAnimation) {
|
||||||
if (!withAnimation) {
|
if (!withAnimation) {
|
||||||
keyPreviewView.setVisibility(View.VISIBLE);
|
keyPreviewView.setVisibility(View.VISIBLE);
|
||||||
|
@ -166,25 +166,25 @@ public final class KeyPreviewChoreographer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Animator createShowUpAnimator(final Key key, final KeyPreviewView keyPreviewView) {
|
public Animator createShowUpAnimator(final Key key, final KeyPreviewView keyPreviewView) {
|
||||||
final Animator animator = mParams.createShowUpAnimator(keyPreviewView);
|
final Animator showUpAnimator = mParams.createShowUpAnimator(keyPreviewView);
|
||||||
animator.addListener(new AnimatorListenerAdapter() {
|
showUpAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationStart(final Animator animator) {
|
public void onAnimationStart(final Animator animator) {
|
||||||
showKeyPreview(key, keyPreviewView, false /* withAnimation */);
|
showKeyPreview(key, keyPreviewView, false /* withAnimation */);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return animator;
|
return showUpAnimator;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Animator createDismissAnimator(final Key key, final KeyPreviewView keyPreviewView) {
|
private Animator createDismissAnimator(final Key key, final KeyPreviewView keyPreviewView) {
|
||||||
final Animator animator = mParams.createDismissAnimator(keyPreviewView);
|
final Animator dismissAnimator = mParams.createDismissAnimator(keyPreviewView);
|
||||||
animator.addListener(new AnimatorListenerAdapter() {
|
dismissAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(final Animator animator) {
|
public void onAnimationEnd(final Animator animator) {
|
||||||
dismissKeyPreview(key, false /* withAnimation */);
|
dismissKeyPreview(key, false /* withAnimation */);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return animator;
|
return dismissAnimator;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class KeyPreviewAnimators extends AnimatorListenerAdapter {
|
private static class KeyPreviewAnimators extends AnimatorListenerAdapter {
|
||||||
|
|
|
@ -733,18 +733,18 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean matchLocaleCodes(TypedArray caseAttr, final Locale[] locales) {
|
private static boolean matchLocaleCodes(TypedArray caseAttr, final Locale[] locales) {
|
||||||
// TODO: adujst this for multilingual input
|
// TODO: adujst this for multilingual input
|
||||||
return matchString(caseAttr, R.styleable.Keyboard_Case_localeCode, locales[0].toString());
|
return matchString(caseAttr, R.styleable.Keyboard_Case_localeCode, locales[0].toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean matchLanguageCodes(TypedArray caseAttr, Locale[] locales) {
|
private static boolean matchLanguageCodes(TypedArray caseAttr, Locale[] locales) {
|
||||||
// TODO: adujst this for multilingual input
|
// TODO: adujst this for multilingual input
|
||||||
return matchString(caseAttr, R.styleable.Keyboard_Case_languageCode,
|
return matchString(caseAttr, R.styleable.Keyboard_Case_languageCode,
|
||||||
locales[0].getLanguage());
|
locales[0].getLanguage());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean matchCountryCodes(TypedArray caseAttr, Locale[] locales) {
|
private static boolean matchCountryCodes(TypedArray caseAttr, Locale[] locales) {
|
||||||
// TODO: adujst this for multilingual input
|
// TODO: adujst this for multilingual input
|
||||||
return matchString(caseAttr, R.styleable.Keyboard_Case_countryCode,
|
return matchString(caseAttr, R.styleable.Keyboard_Case_countryCode,
|
||||||
locales[0].getCountry());
|
locales[0].getCountry());
|
||||||
|
|
|
@ -28,7 +28,8 @@ import java.util.Arrays;
|
||||||
*/
|
*/
|
||||||
@UsedForTesting
|
@UsedForTesting
|
||||||
public class MatrixUtils {
|
public class MatrixUtils {
|
||||||
private static final String TAG = MatrixUtils.class.getSimpleName();
|
static final String TAG = MatrixUtils.class.getSimpleName();
|
||||||
|
|
||||||
public static class MatrixOperationFailedException extends Exception {
|
public static class MatrixOperationFailedException extends Exception {
|
||||||
private static final long serialVersionUID = 4384485606788583829L;
|
private static final long serialVersionUID = 4384485606788583829L;
|
||||||
|
|
||||||
|
|
|
@ -108,9 +108,8 @@ public final class MoreKeySpec {
|
||||||
: Constants.printableCode(mCode));
|
: Constants.printableCode(mCode));
|
||||||
if (StringUtils.codePointCount(label) == 1 && label.codePointAt(0) == mCode) {
|
if (StringUtils.codePointCount(label) == 1 && label.codePointAt(0) == mCode) {
|
||||||
return output;
|
return output;
|
||||||
} else {
|
|
||||||
return label + "|" + output;
|
|
||||||
}
|
}
|
||||||
|
return label + "|" + output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LettersOnBaseLayout {
|
public static class LettersOnBaseLayout {
|
||||||
|
|
|
@ -80,6 +80,7 @@ public final class TouchPositionCorrection {
|
||||||
return mRadii.length;
|
return mRadii.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("static-method")
|
||||||
public float getX(final int row) {
|
public float getX(final int row) {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
// Touch position correction data for X coordinate is obsolete.
|
// Touch position correction data for X coordinate is obsolete.
|
||||||
|
|
|
@ -121,12 +121,11 @@ final public class BinaryDictionaryGetter {
|
||||||
// reason some dictionaries have been installed BUT the dictionary pack can't be
|
// reason some dictionaries have been installed BUT the dictionary pack can't be
|
||||||
// found anymore it's safer to actually supply installed dictionaries.
|
// found anymore it's safer to actually supply installed dictionaries.
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
// The default is true here for the same reasons as above. We got the dictionary
|
|
||||||
// pack but if we don't have any settings for it it means the user has never been
|
|
||||||
// to the settings yet. So by default, the main dictionaries should be on.
|
|
||||||
return mDictPreferences.getBoolean(dictId, true);
|
|
||||||
}
|
}
|
||||||
|
// The default is true here for the same reasons as above. We got the dictionary
|
||||||
|
// pack but if we don't have any settings for it it means the user has never been
|
||||||
|
// to the settings yet. So by default, the main dictionaries should be on.
|
||||||
|
return mDictPreferences.getBoolean(dictId, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ import android.os.SystemClock;
|
||||||
import android.provider.BaseColumns;
|
import android.provider.BaseColumns;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import android.provider.ContactsContract.Contacts;
|
import android.provider.ContactsContract.Contacts;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.inputmethod.annotations.UsedForTesting;
|
import com.android.inputmethod.annotations.UsedForTesting;
|
||||||
|
@ -164,7 +163,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean useFirstLastBigramsForLocale(final Locale locale) {
|
private static boolean useFirstLastBigramsForLocale(final Locale locale) {
|
||||||
// TODO: Add firstname/lastname bigram rules for other languages.
|
// TODO: Add firstname/lastname bigram rules for other languages.
|
||||||
if (locale != null && locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
|
if (locale != null && locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -269,7 +268,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
|
||||||
return end;
|
return end;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean haveContentsChanged() {
|
boolean haveContentsChanged() {
|
||||||
final long startTime = SystemClock.uptimeMillis();
|
final long startTime = SystemClock.uptimeMillis();
|
||||||
final int contactCount = getContactCount();
|
final int contactCount = getContactCount();
|
||||||
if (contactCount > MAX_CONTACT_COUNT) {
|
if (contactCount > MAX_CONTACT_COUNT) {
|
||||||
|
|
|
@ -70,7 +70,7 @@ public final class DicTraverseSession {
|
||||||
mNativeDicTraverseSession, dictionary, previousWord, previousWordLength);
|
mNativeDicTraverseSession, dictionary, previousWord, previousWordLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final long createNativeDicTraverseSession(String locale, long dictSize) {
|
private static long createNativeDicTraverseSession(String locale, long dictSize) {
|
||||||
return setDicTraverseSessionNative(locale, dictSize);
|
return setDicTraverseSessionNative(locale, dictSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,9 +72,13 @@ public abstract class Dictionary {
|
||||||
* Set out of the dictionary types listed above that are based on data specific to the user,
|
* Set out of the dictionary types listed above that are based on data specific to the user,
|
||||||
* e.g., the user's contacts.
|
* e.g., the user's contacts.
|
||||||
*/
|
*/
|
||||||
private static final HashSet<String> sUserSpecificDictionaryTypes =
|
private static final HashSet<String> sUserSpecificDictionaryTypes = new HashSet<>(Arrays.asList(
|
||||||
new HashSet(Arrays.asList(new String[] { TYPE_USER_TYPED, TYPE_USER, TYPE_CONTACTS,
|
TYPE_USER_TYPED,
|
||||||
TYPE_USER_HISTORY, TYPE_PERSONALIZATION, TYPE_CONTEXTUAL }));
|
TYPE_USER,
|
||||||
|
TYPE_CONTACTS,
|
||||||
|
TYPE_USER_HISTORY,
|
||||||
|
TYPE_PERSONALIZATION,
|
||||||
|
TYPE_CONTEXTUAL));
|
||||||
|
|
||||||
public Dictionary(final String dictType, final Locale locale) {
|
public Dictionary(final String dictType, final Locale locale) {
|
||||||
mDictType = dictType;
|
mDictType = dictType;
|
||||||
|
|
|
@ -172,9 +172,8 @@ public class DictionaryFacilitator {
|
||||||
public Dictionary getDict(final String dictType) {
|
public Dictionary getDict(final String dictType) {
|
||||||
if (Dictionary.TYPE_MAIN.equals(dictType)) {
|
if (Dictionary.TYPE_MAIN.equals(dictType)) {
|
||||||
return mMainDict;
|
return mMainDict;
|
||||||
} else {
|
|
||||||
return getSubDict(dictType);
|
|
||||||
}
|
}
|
||||||
|
return getSubDict(dictType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExpandableBinaryDictionary getSubDict(final String dictType) {
|
public ExpandableBinaryDictionary getSubDict(final String dictType) {
|
||||||
|
@ -184,9 +183,8 @@ public class DictionaryFacilitator {
|
||||||
public boolean hasDict(final String dictType) {
|
public boolean hasDict(final String dictType) {
|
||||||
if (Dictionary.TYPE_MAIN.equals(dictType)) {
|
if (Dictionary.TYPE_MAIN.equals(dictType)) {
|
||||||
return mMainDict != null;
|
return mMainDict != null;
|
||||||
} else {
|
|
||||||
return mSubDictMap.containsKey(dictType);
|
|
||||||
}
|
}
|
||||||
|
return mSubDictMap.containsKey(dictType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void closeDict(final String dictType) {
|
public void closeDict(final String dictType) {
|
||||||
|
@ -305,7 +303,7 @@ public class DictionaryFacilitator {
|
||||||
usePersonalizedDicts, forceReloadMainDictionary, listener, "" /* dictNamePrefix */);
|
usePersonalizedDicts, forceReloadMainDictionary, listener, "" /* dictNamePrefix */);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DictionaryGroup findDictionaryGroupWithLocale(final DictionaryGroup[] dictionaryGroups,
|
static DictionaryGroup findDictionaryGroupWithLocale(final DictionaryGroup[] dictionaryGroups,
|
||||||
final Locale locale) {
|
final Locale locale) {
|
||||||
for (int i = 0; i < dictionaryGroups.length; ++i) {
|
for (int i = 0; i < dictionaryGroups.length; ++i) {
|
||||||
if (locale.equals(dictionaryGroups[i].mLocale)) {
|
if (locale.equals(dictionaryGroups[i].mLocale)) {
|
||||||
|
@ -422,34 +420,41 @@ public class DictionaryFacilitator {
|
||||||
ExecutorUtils.getExecutor("InitializeBinaryDictionary").execute(new Runnable() {
|
ExecutorUtils.getExecutor("InitializeBinaryDictionary").execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
for (final Locale locale : locales) {
|
doReloadUninitializedMainDictionaries(
|
||||||
final DictionaryGroup dictionaryGroup =
|
context, locales, listener, latchForWaitingLoadingMainDictionary);
|
||||||
findDictionaryGroupWithLocale(mDictionaryGroups, locale);
|
|
||||||
if (null == dictionaryGroup) {
|
|
||||||
// This should never happen, but better safe than crashy
|
|
||||||
Log.w(TAG, "Expected a dictionary group for " + locale + " but none found");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final Dictionary mainDict =
|
|
||||||
DictionaryFactory.createMainDictionaryFromManager(context, locale);
|
|
||||||
synchronized (mLock) {
|
|
||||||
if (locale.equals(dictionaryGroup.mLocale)) {
|
|
||||||
dictionaryGroup.setMainDict(mainDict);
|
|
||||||
} else {
|
|
||||||
// Dictionary facilitator has been reset for another locale.
|
|
||||||
mainDict.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (listener != null) {
|
|
||||||
listener.onUpdateMainDictionaryAvailability(
|
|
||||||
hasAtLeastOneInitializedMainDictionary());
|
|
||||||
}
|
|
||||||
latchForWaitingLoadingMainDictionary.countDown();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void doReloadUninitializedMainDictionaries(final Context context, final Locale[] locales,
|
||||||
|
final DictionaryInitializationListener listener,
|
||||||
|
final CountDownLatch latchForWaitingLoadingMainDictionary) {
|
||||||
|
for (final Locale locale : locales) {
|
||||||
|
final DictionaryGroup dictionaryGroup =
|
||||||
|
findDictionaryGroupWithLocale(mDictionaryGroups, locale);
|
||||||
|
if (null == dictionaryGroup) {
|
||||||
|
// This should never happen, but better safe than crashy
|
||||||
|
Log.w(TAG, "Expected a dictionary group for " + locale + " but none found");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final Dictionary mainDict =
|
||||||
|
DictionaryFactory.createMainDictionaryFromManager(context, locale);
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (locale.equals(dictionaryGroup.mLocale)) {
|
||||||
|
dictionaryGroup.setMainDict(mainDict);
|
||||||
|
} else {
|
||||||
|
// Dictionary facilitator has been reset for another locale.
|
||||||
|
mainDict.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onUpdateMainDictionaryAvailability(
|
||||||
|
hasAtLeastOneInitializedMainDictionary());
|
||||||
|
}
|
||||||
|
latchForWaitingLoadingMainDictionary.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
@UsedForTesting
|
@UsedForTesting
|
||||||
public void resetDictionariesForTesting(final Context context, final Locale[] locales,
|
public void resetDictionariesForTesting(final Context context, final Locale[] locales,
|
||||||
final ArrayList<String> dictionaryTypes, final HashMap<String, File> dictionaryFiles,
|
final ArrayList<String> dictionaryTypes, final HashMap<String, File> dictionaryFiles,
|
||||||
|
|
|
@ -31,7 +31,7 @@ import android.util.LruCache;
|
||||||
* This class automatically creates and releases facilitator instances using LRU policy.
|
* This class automatically creates and releases facilitator instances using LRU policy.
|
||||||
*/
|
*/
|
||||||
public class DictionaryFacilitatorLruCache {
|
public class DictionaryFacilitatorLruCache {
|
||||||
private static final String TAG = DictionaryFacilitatorLruCache.class.getSimpleName();
|
static final String TAG = DictionaryFacilitatorLruCache.class.getSimpleName();
|
||||||
private static final int WAIT_FOR_LOADING_MAIN_DICT_IN_MILLISECONDS = 1000;
|
private static final int WAIT_FOR_LOADING_MAIN_DICT_IN_MILLISECONDS = 1000;
|
||||||
private static final int MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT = 5;
|
private static final int MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT = 5;
|
||||||
|
|
||||||
|
@ -81,7 +81,8 @@ public class DictionaryFacilitatorLruCache {
|
||||||
mDictionaryNamePrefix = dictionaryNamePrefix;
|
mDictionaryNamePrefix = dictionaryNamePrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void waitForLoadingMainDictionary(final DictionaryFacilitator dictionaryFacilitator) {
|
private static void waitForLoadingMainDictionary(
|
||||||
|
final DictionaryFacilitator dictionaryFacilitator) {
|
||||||
for (int i = 0; i < MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT; i++) {
|
for (int i = 0; i < MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT; i++) {
|
||||||
try {
|
try {
|
||||||
dictionaryFacilitator.waitForLoadingMainDictionaries(
|
dictionaryFacilitator.waitForLoadingMainDictionaries(
|
||||||
|
|
|
@ -21,11 +21,11 @@ import android.util.Log;
|
||||||
|
|
||||||
import com.android.inputmethod.annotations.UsedForTesting;
|
import com.android.inputmethod.annotations.UsedForTesting;
|
||||||
import com.android.inputmethod.keyboard.ProximityInfo;
|
import com.android.inputmethod.keyboard.ProximityInfo;
|
||||||
|
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||||
import com.android.inputmethod.latin.makedict.DictionaryHeader;
|
import com.android.inputmethod.latin.makedict.DictionaryHeader;
|
||||||
import com.android.inputmethod.latin.makedict.FormatSpec;
|
import com.android.inputmethod.latin.makedict.FormatSpec;
|
||||||
import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
|
import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
|
||||||
import com.android.inputmethod.latin.makedict.WordProperty;
|
import com.android.inputmethod.latin.makedict.WordProperty;
|
||||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
|
||||||
import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
|
import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
|
||||||
import com.android.inputmethod.latin.utils.AsyncResultHolder;
|
import com.android.inputmethod.latin.utils.AsyncResultHolder;
|
||||||
import com.android.inputmethod.latin.utils.CombinedFormatUtils;
|
import com.android.inputmethod.latin.utils.CombinedFormatUtils;
|
||||||
|
@ -47,6 +47,7 @@ import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for an expandable dictionary that can be created and updated dynamically
|
* Abstract base class for an expandable dictionary that can be created and updated dynamically
|
||||||
|
@ -107,11 +108,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
*/
|
*/
|
||||||
protected abstract void loadInitialContentsLocked();
|
protected abstract void loadInitialContentsLocked();
|
||||||
|
|
||||||
private boolean matchesExpectedBinaryDictFormatVersionForThisType(final int formatVersion) {
|
static boolean matchesExpectedBinaryDictFormatVersionForThisType(final int formatVersion) {
|
||||||
return formatVersion == FormatSpec.VERSION4;
|
return formatVersion == FormatSpec.VERSION4;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean needsToMigrateDictionary(final int formatVersion) {
|
private static boolean needsToMigrateDictionary(final int formatVersion) {
|
||||||
// When we bump up the dictionary format version, the old version should be added to here
|
// When we bump up the dictionary format version, the old version should be added to here
|
||||||
// for supporting migration. Note that native code has to support reading such formats.
|
// for supporting migration. Note that native code has to support reading such formats.
|
||||||
return formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING;
|
return formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING;
|
||||||
|
@ -159,7 +160,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
asyncExecuteTaskWithLock(mLock.writeLock(), mDictName /* executorName */, task);
|
asyncExecuteTaskWithLock(mLock.writeLock(), mDictName /* executorName */, task);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void asyncExecuteTaskWithLock(final Lock lock, final String executorName,
|
private static void asyncExecuteTaskWithLock(final Lock lock, final String executorName,
|
||||||
final Runnable task) {
|
final Runnable task) {
|
||||||
asyncPreCheckAndExecuteTaskWithLock(lock, null /* preCheckTask */, executorName, task);
|
asyncPreCheckAndExecuteTaskWithLock(lock, null /* preCheckTask */, executorName, task);
|
||||||
}
|
}
|
||||||
|
@ -172,8 +173,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute task with lock when the result of preCheckTask is true or preCheckTask is null.
|
// Execute task with lock when the result of preCheckTask is true or preCheckTask is null.
|
||||||
private void asyncPreCheckAndExecuteTaskWithLock(final Lock lock,
|
private static void asyncPreCheckAndExecuteTaskWithLock(final Lock lock,
|
||||||
final Callable<Boolean> preCheckTask, final String executorName, final Runnable task) {
|
final Callable<Boolean> preCheckTask, final String executorName, final Runnable task) {
|
||||||
|
final String tag = TAG;
|
||||||
ExecutorUtils.getExecutor(executorName).execute(new Runnable() {
|
ExecutorUtils.getExecutor(executorName).execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -183,7 +185,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
Log.e(TAG, "The pre check task throws an exception.", e);
|
Log.e(tag, "The pre check task throws an exception.", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,6 +199,18 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
BinaryDictionary getBinaryDictionary() {
|
||||||
|
return mBinaryDictionary;
|
||||||
|
}
|
||||||
|
|
||||||
|
void closeBinaryDictionary() {
|
||||||
|
if (mBinaryDictionary != null) {
|
||||||
|
mBinaryDictionary.close();
|
||||||
|
mBinaryDictionary = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes and cleans up the binary dictionary.
|
* Closes and cleans up the binary dictionary.
|
||||||
*/
|
*/
|
||||||
|
@ -205,10 +219,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
asyncExecuteTaskWithWriteLock(new Runnable() {
|
asyncExecuteTaskWithWriteLock(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (mBinaryDictionary != null) {
|
closeBinaryDictionary();
|
||||||
mBinaryDictionary.close();
|
|
||||||
mBinaryDictionary = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -234,14 +245,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeBinaryDictionaryLocked() {
|
void removeBinaryDictionaryLocked() {
|
||||||
if (mBinaryDictionary != null) {
|
closeBinaryDictionary();
|
||||||
mBinaryDictionary.close();
|
|
||||||
}
|
|
||||||
if (mDictFile.exists() && !FileUtils.deleteRecursively(mDictFile)) {
|
if (mDictFile.exists() && !FileUtils.deleteRecursively(mDictFile)) {
|
||||||
Log.e(TAG, "Can't remove a file: " + mDictFile.getName());
|
Log.e(TAG, "Can't remove a file: " + mDictFile.getName());
|
||||||
}
|
}
|
||||||
mBinaryDictionary = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openBinaryDictionaryLocked() {
|
private void openBinaryDictionaryLocked() {
|
||||||
|
@ -250,7 +258,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
true /* useFullEditDistance */, mLocale, mDictType, true /* isUpdatable */);
|
true /* useFullEditDistance */, mLocale, mDictType, true /* isUpdatable */);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createOnMemoryBinaryDictionaryLocked() {
|
void createOnMemoryBinaryDictionaryLocked() {
|
||||||
mBinaryDictionary = new BinaryDictionary(
|
mBinaryDictionary = new BinaryDictionary(
|
||||||
mDictFile.getAbsolutePath(), true /* useFullEditDistance */, mLocale, mDictType,
|
mDictFile.getAbsolutePath(), true /* useFullEditDistance */, mLocale, mDictType,
|
||||||
DICTIONARY_FORMAT_VERSION, getHeaderAttributeMap());
|
DICTIONARY_FORMAT_VERSION, getHeaderAttributeMap());
|
||||||
|
@ -273,7 +281,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
asyncExecuteTaskWithWriteLock(new Runnable() {
|
asyncExecuteTaskWithWriteLock(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (mBinaryDictionary == null) {
|
if (getBinaryDictionary() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runGCIfRequiredLocked(mindsBlockByGC);
|
runGCIfRequiredLocked(mindsBlockByGC);
|
||||||
|
@ -291,24 +299,24 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
@Nonnull final Runnable updateTask,
|
@Nonnull final Runnable updateTask,
|
||||||
@Nonnull final String word, @Nonnull final DistracterFilter distracterFilter) {
|
@Nonnull final String word, @Nonnull final DistracterFilter distracterFilter) {
|
||||||
reloadDictionaryIfRequired();
|
reloadDictionaryIfRequired();
|
||||||
asyncPreCheckAndExecuteTaskWithWriteLock(
|
final Callable<Boolean> preCheckTask = new Callable<Boolean>() {
|
||||||
new Callable<Boolean>() {
|
@Override
|
||||||
@Override
|
public Boolean call() throws Exception {
|
||||||
public Boolean call() throws Exception {
|
return !distracterFilter.isDistracterToWordsInDictionaries(
|
||||||
return !distracterFilter.isDistracterToWordsInDictionaries(
|
NgramContext.EMPTY_PREV_WORDS_INFO, word, mLocale);
|
||||||
NgramContext.EMPTY_PREV_WORDS_INFO, word, mLocale);
|
}
|
||||||
}
|
};
|
||||||
},
|
final Runnable task = new Runnable() {
|
||||||
new Runnable() {
|
@Override
|
||||||
@Override
|
public void run() {
|
||||||
public void run() {
|
if (getBinaryDictionary() == null) {
|
||||||
if (mBinaryDictionary == null) {
|
return;
|
||||||
return;
|
}
|
||||||
}
|
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
||||||
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
updateTask.run();
|
||||||
updateTask.run();
|
}
|
||||||
}
|
};
|
||||||
});
|
asyncPreCheckAndExecuteTaskWithWriteLock(preCheckTask, task);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -344,11 +352,12 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
asyncExecuteTaskWithWriteLock(new Runnable() {
|
asyncExecuteTaskWithWriteLock(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (mBinaryDictionary == null) {
|
final BinaryDictionary binaryDictionary = getBinaryDictionary();
|
||||||
|
if (binaryDictionary == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
||||||
if (!mBinaryDictionary.removeUnigramEntry(word)) {
|
if (!binaryDictionary.removeUnigramEntry(word)) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.i(TAG, "Cannot remove unigram entry: " + word);
|
Log.i(TAG, "Cannot remove unigram entry: " + word);
|
||||||
}
|
}
|
||||||
|
@ -366,7 +375,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
asyncExecuteTaskWithWriteLock(new Runnable() {
|
asyncExecuteTaskWithWriteLock(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (mBinaryDictionary == null) {
|
if (getBinaryDictionary() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
||||||
|
@ -395,11 +404,12 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
asyncExecuteTaskWithWriteLock(new Runnable() {
|
asyncExecuteTaskWithWriteLock(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (mBinaryDictionary == null) {
|
final BinaryDictionary binaryDictionary = getBinaryDictionary();
|
||||||
|
if (binaryDictionary == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
||||||
if (!mBinaryDictionary.removeNgramEntry(ngramContext, word)) {
|
if (!binaryDictionary.removeNgramEntry(ngramContext, word)) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.i(TAG, "Cannot remove n-gram entry.");
|
Log.i(TAG, "Cannot remove n-gram entry.");
|
||||||
Log.i(TAG, " NgramContext: " + ngramContext + ", word: " + word);
|
Log.i(TAG, " NgramContext: " + ngramContext + ", word: " + word);
|
||||||
|
@ -418,7 +428,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
updateDictionaryWithWriteLockIfWordIsNotADistracter(new Runnable() {
|
updateDictionaryWithWriteLockIfWordIsNotADistracter(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!mBinaryDictionary.updateEntriesForWordWithNgramContext(ngramContext, word,
|
final BinaryDictionary binaryDictionary = getBinaryDictionary();
|
||||||
|
if (binaryDictionary == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!binaryDictionary.updateEntriesForWordWithNgramContext(ngramContext, word,
|
||||||
isValidWord, count, timestamp)) {
|
isValidWord, count, timestamp)) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.e(TAG, "Cannot update counter. word: " + word
|
Log.e(TAG, "Cannot update counter. word: " + word
|
||||||
|
@ -444,10 +458,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
if (mBinaryDictionary == null) {
|
final BinaryDictionary binaryDictionary = getBinaryDictionary();
|
||||||
|
if (binaryDictionary == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mBinaryDictionary.addMultipleDictionaryEntries(
|
binaryDictionary.addMultipleDictionaryEntries(
|
||||||
languageModelParams.toArray(
|
languageModelParams.toArray(
|
||||||
new LanguageModelParam[languageModelParams.size()]));
|
new LanguageModelParam[languageModelParams.size()]));
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -555,7 +570,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
* Loads the current binary dictionary from internal storage. Assumes the dictionary file
|
* Loads the current binary dictionary from internal storage. Assumes the dictionary file
|
||||||
* exists.
|
* exists.
|
||||||
*/
|
*/
|
||||||
private void loadBinaryDictionaryLocked() {
|
void loadBinaryDictionaryLocked() {
|
||||||
if (DBG_STRESS_TEST) {
|
if (DBG_STRESS_TEST) {
|
||||||
// Test if this class does not cause problems when it takes long time to load binary
|
// Test if this class does not cause problems when it takes long time to load binary
|
||||||
// dictionary.
|
// dictionary.
|
||||||
|
@ -583,7 +598,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
/**
|
/**
|
||||||
* Create a new binary dictionary and load initial contents.
|
* Create a new binary dictionary and load initial contents.
|
||||||
*/
|
*/
|
||||||
private void createNewDictionaryLocked() {
|
void createNewDictionaryLocked() {
|
||||||
removeBinaryDictionaryLocked();
|
removeBinaryDictionaryLocked();
|
||||||
createOnMemoryBinaryDictionaryLocked();
|
createOnMemoryBinaryDictionaryLocked();
|
||||||
loadInitialContentsLocked();
|
loadInitialContentsLocked();
|
||||||
|
@ -599,6 +614,14 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
mNeedsToRecreate = true;
|
mNeedsToRecreate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clearNeedsToRecreate() {
|
||||||
|
mNeedsToRecreate = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isNeededToRecreate() {
|
||||||
|
return mNeedsToRecreate;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the current binary dictionary from internal storage. If the dictionary file doesn't
|
* Load the current binary dictionary from internal storage. If the dictionary file doesn't
|
||||||
* exists or needs to be regenerated, the new dictionary file will be asynchronously generated.
|
* exists or needs to be regenerated, the new dictionary file will be asynchronously generated.
|
||||||
|
@ -621,35 +644,39 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
* Reloads the dictionary. Access is controlled on a per dictionary file basis.
|
* Reloads the dictionary. Access is controlled on a per dictionary file basis.
|
||||||
*/
|
*/
|
||||||
private final void asyncReloadDictionary() {
|
private final void asyncReloadDictionary() {
|
||||||
if (mIsReloading.compareAndSet(false, true)) {
|
final AtomicBoolean isReloading = mIsReloading;
|
||||||
asyncExecuteTaskWithWriteLock(new Runnable() {
|
if (!isReloading.compareAndSet(false, true)) {
|
||||||
@Override
|
return;
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
if (!mDictFile.exists() || mNeedsToRecreate) {
|
|
||||||
// If the dictionary file does not exist or contents have been updated,
|
|
||||||
// generate a new one.
|
|
||||||
createNewDictionaryLocked();
|
|
||||||
} else if (mBinaryDictionary == null) {
|
|
||||||
// Otherwise, load the existing dictionary.
|
|
||||||
loadBinaryDictionaryLocked();
|
|
||||||
if (mBinaryDictionary != null && !(isValidDictionaryLocked()
|
|
||||||
// TODO: remove the check below
|
|
||||||
&& matchesExpectedBinaryDictFormatVersionForThisType(
|
|
||||||
mBinaryDictionary.getFormatVersion()))) {
|
|
||||||
// Binary dictionary or its format version is not valid. Regenerate
|
|
||||||
// the dictionary file. createNewDictionaryLocked will remove the
|
|
||||||
// existing files if appropriate.
|
|
||||||
createNewDictionaryLocked();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mNeedsToRecreate = false;
|
|
||||||
} finally {
|
|
||||||
mIsReloading.set(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
final File dictFile = mDictFile;
|
||||||
|
asyncExecuteTaskWithWriteLock(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
if (!dictFile.exists() || isNeededToRecreate()) {
|
||||||
|
// If the dictionary file does not exist or contents have been updated,
|
||||||
|
// generate a new one.
|
||||||
|
createNewDictionaryLocked();
|
||||||
|
} else if (getBinaryDictionary() == null) {
|
||||||
|
// Otherwise, load the existing dictionary.
|
||||||
|
loadBinaryDictionaryLocked();
|
||||||
|
final BinaryDictionary binaryDictionary = getBinaryDictionary();
|
||||||
|
if (binaryDictionary != null && !(isValidDictionaryLocked()
|
||||||
|
// TODO: remove the check below
|
||||||
|
&& matchesExpectedBinaryDictFormatVersionForThisType(
|
||||||
|
binaryDictionary.getFormatVersion()))) {
|
||||||
|
// Binary dictionary or its format version is not valid. Regenerate
|
||||||
|
// the dictionary file. createNewDictionaryLocked will remove the
|
||||||
|
// existing files if appropriate.
|
||||||
|
createNewDictionaryLocked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clearNeedsToRecreate();
|
||||||
|
} finally {
|
||||||
|
isReloading.set(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -659,19 +686,20 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
asyncExecuteTaskWithWriteLock(new Runnable() {
|
asyncExecuteTaskWithWriteLock(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (mBinaryDictionary == null) {
|
final BinaryDictionary binaryDictionary = getBinaryDictionary();
|
||||||
|
if (binaryDictionary == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mBinaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
|
if (binaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
|
||||||
mBinaryDictionary.flushWithGC();
|
binaryDictionary.flushWithGC();
|
||||||
} else {
|
} else {
|
||||||
mBinaryDictionary.flush();
|
binaryDictionary.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int parseEntryCount(final String entryCountStr) {
|
static int parseEntryCount(final String entryCountStr) {
|
||||||
int entryCount;
|
int entryCount;
|
||||||
try {
|
try {
|
||||||
entryCount = Integer.parseInt(entryCountStr);
|
entryCount = Integer.parseInt(entryCountStr);
|
||||||
|
@ -683,23 +711,27 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
|
|
||||||
public DictionaryStats getDictionaryStats() {
|
public DictionaryStats getDictionaryStats() {
|
||||||
reloadDictionaryIfRequired();
|
reloadDictionaryIfRequired();
|
||||||
|
final String dictName = mDictName;
|
||||||
|
final File dictFile = mDictFile;
|
||||||
final AsyncResultHolder<DictionaryStats> result = new AsyncResultHolder<>();
|
final AsyncResultHolder<DictionaryStats> result = new AsyncResultHolder<>();
|
||||||
asyncExecuteTaskWithLock(mLock.readLock(), mDictName /* executorName */, new Runnable() {
|
asyncExecuteTaskWithLock(mLock.readLock(), dictName /* executorName */, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (mBinaryDictionary == null) {
|
final BinaryDictionary binaryDictionary = getBinaryDictionary();
|
||||||
result.set(new DictionaryStats(mLocale, mDictName, mDictFile,
|
if (binaryDictionary == null) {
|
||||||
|
result.set(new DictionaryStats(mLocale, dictName, dictFile,
|
||||||
DictionaryStats.NOT_AN_ENTRY_COUNT,
|
DictionaryStats.NOT_AN_ENTRY_COUNT,
|
||||||
DictionaryStats.NOT_AN_ENTRY_COUNT));
|
DictionaryStats.NOT_AN_ENTRY_COUNT));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
final int unigramCount = parseEntryCount(
|
final int unigramCount = parseEntryCount(
|
||||||
mBinaryDictionary.getPropertyForGettingStats(
|
binaryDictionary.getPropertyForGettingStats(
|
||||||
BinaryDictionary.MAX_UNIGRAM_COUNT_QUERY));
|
BinaryDictionary.MAX_UNIGRAM_COUNT_QUERY));
|
||||||
// TODO: Get dedicated entry counts for bigram, trigram, and so on.
|
// TODO: Get dedicated entry counts for bigram, trigram, and so on.
|
||||||
final int ngramCount = parseEntryCount(mBinaryDictionary.getPropertyForGettingStats(
|
final int ngramCount = parseEntryCount(binaryDictionary.getPropertyForGettingStats(
|
||||||
BinaryDictionary.MAX_BIGRAM_COUNT_QUERY));
|
BinaryDictionary.MAX_BIGRAM_COUNT_QUERY));
|
||||||
// TODO: Get more information from dictionary.
|
// TODO: Get more information from dictionary.
|
||||||
result.set(new DictionaryStats(mLocale, mDictName, mDictFile, unigramCount,
|
result.set(new DictionaryStats(mLocale, dictName, dictFile, unigramCount,
|
||||||
ngramCount));
|
ngramCount));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -731,28 +763,34 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
|
|
||||||
public void dumpAllWordsForDebug() {
|
public void dumpAllWordsForDebug() {
|
||||||
reloadDictionaryIfRequired();
|
reloadDictionaryIfRequired();
|
||||||
|
final String tag = TAG;
|
||||||
|
final String dictName = mDictName;
|
||||||
asyncExecuteTaskWithLock(mLock.readLock(), "dumpAllWordsForDebug", new Runnable() {
|
asyncExecuteTaskWithLock(mLock.readLock(), "dumpAllWordsForDebug", new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Log.d(TAG, "Dump dictionary: " + mDictName + " for " + mLocale);
|
Log.d(tag, "Dump dictionary: " + dictName + " for " + mLocale);
|
||||||
|
final BinaryDictionary binaryDictionary = getBinaryDictionary();
|
||||||
|
if (binaryDictionary == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
final DictionaryHeader header = mBinaryDictionary.getHeader();
|
final DictionaryHeader header = binaryDictionary.getHeader();
|
||||||
Log.d(TAG, "Format version: " + mBinaryDictionary.getFormatVersion());
|
Log.d(tag, "Format version: " + binaryDictionary.getFormatVersion());
|
||||||
Log.d(TAG, CombinedFormatUtils.formatAttributeMap(
|
Log.d(tag, CombinedFormatUtils.formatAttributeMap(
|
||||||
header.mDictionaryOptions.mAttributes));
|
header.mDictionaryOptions.mAttributes));
|
||||||
} catch (final UnsupportedFormatException e) {
|
} catch (final UnsupportedFormatException e) {
|
||||||
Log.d(TAG, "Cannot fetch header information.", e);
|
Log.d(tag, "Cannot fetch header information.", e);
|
||||||
}
|
}
|
||||||
int token = 0;
|
int token = 0;
|
||||||
do {
|
do {
|
||||||
final BinaryDictionary.GetNextWordPropertyResult result =
|
final BinaryDictionary.GetNextWordPropertyResult result =
|
||||||
mBinaryDictionary.getNextWordProperty(token);
|
binaryDictionary.getNextWordProperty(token);
|
||||||
final WordProperty wordProperty = result.mWordProperty;
|
final WordProperty wordProperty = result.mWordProperty;
|
||||||
if (wordProperty == null) {
|
if (wordProperty == null) {
|
||||||
Log.d(TAG, " dictionary is empty.");
|
Log.d(tag, " dictionary is empty.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Log.d(TAG, wordProperty.toString());
|
Log.d(tag, wordProperty.toString());
|
||||||
token = result.mNextToken;
|
token = result.mNextToken;
|
||||||
} while (token != 0);
|
} while (token != 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,15 +119,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
SuggestionStripView.Listener, SuggestionStripViewAccessor,
|
SuggestionStripView.Listener, SuggestionStripViewAccessor,
|
||||||
DictionaryFacilitator.DictionaryInitializationListener,
|
DictionaryFacilitator.DictionaryInitializationListener,
|
||||||
ImportantNoticeDialog.ImportantNoticeDialogListener {
|
ImportantNoticeDialog.ImportantNoticeDialogListener {
|
||||||
private static final String TAG = LatinIME.class.getSimpleName();
|
static final String TAG = LatinIME.class.getSimpleName();
|
||||||
private static final boolean TRACE = false;
|
private static final boolean TRACE = false;
|
||||||
private static boolean DEBUG = false;
|
private static boolean DEBUG = false;
|
||||||
|
|
||||||
private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100;
|
private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100;
|
||||||
private static final int PERIOD_FOR_AUDIO_AND_HAPTIC_FEEDBACK_IN_KEY_REPEAT = 2;
|
private static final int PERIOD_FOR_AUDIO_AND_HAPTIC_FEEDBACK_IN_KEY_REPEAT = 2;
|
||||||
private static final int PENDING_IMS_CALLBACK_DURATION_MILLIS = 800;
|
private static final int PENDING_IMS_CALLBACK_DURATION_MILLIS = 800;
|
||||||
private static final long DELAY_WAIT_FOR_DICTIONARY_LOAD_MILLIS = TimeUnit.SECONDS.toMillis(2);
|
static final long DELAY_WAIT_FOR_DICTIONARY_LOAD_MILLIS = TimeUnit.SECONDS.toMillis(2);
|
||||||
private static final long DELAY_DEALLOCATE_MEMORY_MILLIS = TimeUnit.SECONDS.toMillis(10);
|
static final long DELAY_DEALLOCATE_MEMORY_MILLIS = TimeUnit.SECONDS.toMillis(10);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the scheme used by the Package Manager to warn of a new package installation,
|
* The name of the scheme used by the Package Manager to warn of a new package installation,
|
||||||
|
@ -135,7 +135,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
*/
|
*/
|
||||||
private static final String SCHEME_PACKAGE = "package";
|
private static final String SCHEME_PACKAGE = "package";
|
||||||
|
|
||||||
private final Settings mSettings;
|
final Settings mSettings;
|
||||||
private final DictionaryFacilitator mDictionaryFacilitator =
|
private final DictionaryFacilitator mDictionaryFacilitator =
|
||||||
new DictionaryFacilitator(this /* context */);
|
new DictionaryFacilitator(this /* context */);
|
||||||
// TODO: Move from LatinIME.
|
// TODO: Move from LatinIME.
|
||||||
|
@ -149,7 +149,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
mHandler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE);
|
mHandler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
private final InputLogic mInputLogic = new InputLogic(this /* LatinIME */,
|
final InputLogic mInputLogic = new InputLogic(this /* LatinIME */,
|
||||||
this /* SuggestionStripViewAccessor */, mDictionaryFacilitator);
|
this /* SuggestionStripViewAccessor */, mDictionaryFacilitator);
|
||||||
// We expect to have only one decoder in almost all cases, hence the default capacity of 1.
|
// We expect to have only one decoder in almost all cases, hence the default capacity of 1.
|
||||||
// If it turns out we need several, it will get grown seamlessly.
|
// If it turns out we need several, it will get grown seamlessly.
|
||||||
|
@ -163,7 +163,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
|
|
||||||
private RichInputMethodManager mRichImm;
|
private RichInputMethodManager mRichImm;
|
||||||
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
|
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
|
||||||
private final SubtypeSwitcher mSubtypeSwitcher;
|
final SubtypeSwitcher mSubtypeSwitcher;
|
||||||
private final SubtypeState mSubtypeState = new SubtypeState();
|
private final SubtypeState mSubtypeState = new SubtypeState();
|
||||||
private final SpecialKeyDetector mSpecialKeyDetector;
|
private final SpecialKeyDetector mSpecialKeyDetector;
|
||||||
private StatsUtilsManager mStatsUtilsManager;
|
private StatsUtilsManager mStatsUtilsManager;
|
||||||
|
@ -204,7 +204,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1;
|
private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1;
|
||||||
private static final int ARG1_SHOW_GESTURE_FLOATING_PREVIEW_TEXT = 2;
|
private static final int ARG1_SHOW_GESTURE_FLOATING_PREVIEW_TEXT = 2;
|
||||||
private static final int ARG2_UNUSED = 0;
|
private static final int ARG2_UNUSED = 0;
|
||||||
private static final int ARG1_FALSE = 0;
|
|
||||||
private static final int ARG1_TRUE = 1;
|
private static final int ARG1_TRUE = 1;
|
||||||
|
|
||||||
private int mDelayInMillisecondsToUpdateSuggestions;
|
private int mDelayInMillisecondsToUpdateSuggestions;
|
||||||
|
@ -654,7 +653,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetDictionaryFacilitatorIfNecessary() {
|
void resetDictionaryFacilitatorIfNecessary() {
|
||||||
final Locale[] subtypeSwitcherLocales = mSubtypeSwitcher.getCurrentSubtypeLocales();
|
final Locale[] subtypeSwitcherLocales = mSubtypeSwitcher.getCurrentSubtypeLocales();
|
||||||
if (mDictionaryFacilitator.isForLocales(subtypeSwitcherLocales)) {
|
if (mDictionaryFacilitator.isForLocales(subtypeSwitcherLocales)) {
|
||||||
return;
|
return;
|
||||||
|
@ -791,17 +790,21 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateCursorAnchorInfo() {
|
||||||
|
// CursorAnchorInfo is used on L and later.
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
if (isFullscreenMode() && mExtractEditText != null) {
|
||||||
|
mInputLogic.onUpdateCursorAnchorInfo(
|
||||||
|
CursorAnchorInfoUtils.extractFromTextView(mExtractEditText));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final ViewTreeObserver.OnPreDrawListener mExtractTextViewPreDrawListener =
|
private final ViewTreeObserver.OnPreDrawListener mExtractTextViewPreDrawListener =
|
||||||
new ViewTreeObserver.OnPreDrawListener() {
|
new ViewTreeObserver.OnPreDrawListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreDraw() {
|
public boolean onPreDraw() {
|
||||||
// CursorAnchorInfo is used on L and later.
|
updateCursorAnchorInfo();
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
if (isFullscreenMode() && mExtractEditText != null) {
|
|
||||||
mInputLogic.onUpdateCursorAnchorInfo(
|
|
||||||
CursorAnchorInfoUtils.extractFromTextView(mExtractEditText));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -846,12 +849,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
loadKeyboard();
|
loadKeyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {
|
void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {
|
||||||
super.onStartInput(editorInfo, restarting);
|
super.onStartInput(editorInfo, restarting);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
private void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) {
|
void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) {
|
||||||
super.onStartInputView(editorInfo, restarting);
|
super.onStartInputView(editorInfo, restarting);
|
||||||
// Switch to the null consumer to handle cases leading to early exit below, for which we
|
// Switch to the null consumer to handle cases leading to early exit below, for which we
|
||||||
// also wouldn't be consuming gesture data.
|
// also wouldn't be consuming gesture data.
|
||||||
|
@ -1034,7 +1037,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onFinishInputInternal() {
|
void onFinishInputInternal() {
|
||||||
super.onFinishInput();
|
super.onFinishInput();
|
||||||
|
|
||||||
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
|
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
|
||||||
|
@ -1043,7 +1046,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onFinishInputViewInternal(final boolean finishingInput) {
|
void onFinishInputViewInternal(final boolean finishingInput) {
|
||||||
super.onFinishInputView(finishingInput);
|
super.onFinishInputView(finishingInput);
|
||||||
cleanupInternalStateForFinishInput();
|
cleanupInternalStateForFinishInput();
|
||||||
}
|
}
|
||||||
|
@ -1295,11 +1298,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getCurrentAutoCapsState() {
|
int getCurrentAutoCapsState() {
|
||||||
return mInputLogic.getCurrentAutoCapsState(mSettings.getCurrent());
|
return mInputLogic.getCurrentAutoCapsState(mSettings.getCurrent());
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getCurrentRecapitalizeState() {
|
int getCurrentRecapitalizeState() {
|
||||||
return mInputLogic.getCurrentRecapitalizeState();
|
return mInputLogic.getCurrentRecapitalizeState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1389,12 +1392,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
final Keyboard currentKeyboard = mKeyboardSwitcher.getKeyboard();
|
final Keyboard currentKeyboard = mKeyboardSwitcher.getKeyboard();
|
||||||
if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) {
|
if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) {
|
||||||
return codePoint;
|
return codePoint;
|
||||||
} else {
|
|
||||||
return Constants.CODE_SYMBOL_SHIFT;
|
|
||||||
}
|
}
|
||||||
} else {
|
return Constants.CODE_SYMBOL_SHIFT;
|
||||||
return codePoint;
|
|
||||||
}
|
}
|
||||||
|
return codePoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of {@link KeyboardActionListener}.
|
// Implementation of {@link KeyboardActionListener}.
|
||||||
|
@ -1496,7 +1497,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method must run on the UI Thread.
|
// This method must run on the UI Thread.
|
||||||
private void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords,
|
void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords,
|
||||||
final boolean dismissGestureFloatingPreviewText) {
|
final boolean dismissGestureFloatingPreviewText) {
|
||||||
showSuggestionStrip(suggestedWords);
|
showSuggestionStrip(suggestedWords);
|
||||||
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
|
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
|
||||||
|
@ -1812,7 +1813,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private void launchSettings() {
|
void launchSettings() {
|
||||||
mInputLogic.commitTyped(mSettings.getCurrent(), LastComposedWord.NOT_A_SEPARATOR);
|
mInputLogic.commitTyped(mSettings.getCurrent(), LastComposedWord.NOT_A_SEPARATOR);
|
||||||
requestHideSelf(0);
|
requestHideSelf(0);
|
||||||
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
|
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
|
||||||
|
@ -1836,6 +1837,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
languageSelectionTitle,
|
languageSelectionTitle,
|
||||||
getString(ApplicationUtils.getActivityTitleResId(this, SettingsActivity.class))
|
getString(ApplicationUtils.getActivityTitleResId(this, SettingsActivity.class))
|
||||||
};
|
};
|
||||||
|
final String imeId = mRichImm.getInputMethodIdOfThisIme();
|
||||||
final OnClickListener listener = new OnClickListener() {
|
final OnClickListener listener = new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface di, int position) {
|
public void onClick(DialogInterface di, int position) {
|
||||||
|
@ -1843,7 +1845,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
switch (position) {
|
switch (position) {
|
||||||
case 0:
|
case 0:
|
||||||
final Intent intent = IntentUtils.getInputLanguageSelectionIntent(
|
final Intent intent = IntentUtils.getInputLanguageSelectionIntent(
|
||||||
mRichImm.getInputMethodIdOfThisIme(),
|
imeId,
|
||||||
Intent.FLAG_ACTIVITY_NEW_TASK
|
Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
|
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
|
||||||
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
|
|
@ -31,14 +31,14 @@ public class NgramContext {
|
||||||
public static final NgramContext EMPTY_PREV_WORDS_INFO =
|
public static final NgramContext EMPTY_PREV_WORDS_INFO =
|
||||||
new NgramContext(WordInfo.EMPTY_WORD_INFO);
|
new NgramContext(WordInfo.EMPTY_WORD_INFO);
|
||||||
public static final NgramContext BEGINNING_OF_SENTENCE =
|
public static final NgramContext BEGINNING_OF_SENTENCE =
|
||||||
new NgramContext(WordInfo.BEGINNING_OF_SENTENCE);
|
new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Word information used to represent previous words information.
|
* Word information used to represent previous words information.
|
||||||
*/
|
*/
|
||||||
public static class WordInfo {
|
public static class WordInfo {
|
||||||
public static final WordInfo EMPTY_WORD_INFO = new WordInfo(null);
|
public static final WordInfo EMPTY_WORD_INFO = new WordInfo(null);
|
||||||
public static final WordInfo BEGINNING_OF_SENTENCE = new WordInfo();
|
public static final WordInfo BEGINNING_OF_SENTENCE_WORD_INFO = new WordInfo();
|
||||||
|
|
||||||
// This is an empty char sequence when mIsBeginningOfSentence is true.
|
// This is an empty char sequence when mIsBeginningOfSentence is true.
|
||||||
public final CharSequence mWord;
|
public final CharSequence mWord;
|
||||||
|
@ -48,7 +48,7 @@ public class NgramContext {
|
||||||
public final boolean mIsBeginningOfSentence;
|
public final boolean mIsBeginningOfSentence;
|
||||||
|
|
||||||
// Beginning of sentence.
|
// Beginning of sentence.
|
||||||
public WordInfo() {
|
private WordInfo() {
|
||||||
mWord = "";
|
mWord = "";
|
||||||
mIsBeginningOfSentence = true;
|
mIsBeginningOfSentence = true;
|
||||||
}
|
}
|
||||||
|
@ -96,18 +96,6 @@ public class NgramContext {
|
||||||
mPrevWordsCount = prevWordsInfo.length;
|
mPrevWordsCount = prevWordsInfo.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct from WordInfo array and size. The caller shouldn't change prevWordsInfo after
|
|
||||||
// calling this method.
|
|
||||||
private NgramContext(final NgramContext ngramContext, final int prevWordsCount) {
|
|
||||||
if (ngramContext.mPrevWordsCount < prevWordsCount) {
|
|
||||||
throw new IndexOutOfBoundsException("ngramContext.mPrevWordsCount ("
|
|
||||||
+ ngramContext.mPrevWordsCount + ") is smaller than prevWordsCount ("
|
|
||||||
+ prevWordsCount + ")");
|
|
||||||
}
|
|
||||||
mPrevWordsInfo = ngramContext.mPrevWordsInfo;
|
|
||||||
mPrevWordsCount = prevWordsCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create next prevWordsInfo using current prevWordsInfo.
|
// Create next prevWordsInfo using current prevWordsInfo.
|
||||||
public NgramContext getNextNgramContext(final WordInfo wordInfo) {
|
public NgramContext getNextNgramContext(final WordInfo wordInfo) {
|
||||||
final int nextPrevWordCount = Math.min(Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM,
|
final int nextPrevWordCount = Math.min(Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM,
|
||||||
|
|
|
@ -44,8 +44,6 @@ import com.android.inputmethod.latin.utils.SpannableStringUtils;
|
||||||
import com.android.inputmethod.latin.utils.StringUtils;
|
import com.android.inputmethod.latin.utils.StringUtils;
|
||||||
import com.android.inputmethod.latin.utils.TextRange;
|
import com.android.inputmethod.latin.utils.TextRange;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enrichment class for InputConnection to simplify interaction and add functionality.
|
* Enrichment class for InputConnection to simplify interaction and add functionality.
|
||||||
*
|
*
|
||||||
|
@ -91,7 +89,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This variable is a temporary object used in
|
* This variable is a temporary object used in
|
||||||
* {@link #commitTextWithBackgroundColor(CharSequence, int, int)} to avoid object creation.
|
* {@link #commitTextWithBackgroundColor(CharSequence,int,int,int)} to avoid object creation.
|
||||||
*/
|
*/
|
||||||
private SpannableStringBuilder mTempObjectForCommitText = new SpannableStringBuilder();
|
private SpannableStringBuilder mTempObjectForCommitText = new SpannableStringBuilder();
|
||||||
/**
|
/**
|
||||||
|
@ -151,9 +149,8 @@ public final class RichInputConnection implements PrivateCommandPerformer {
|
||||||
} else {
|
} else {
|
||||||
if (DBG) {
|
if (DBG) {
|
||||||
throw new RuntimeException("Nest level too deep");
|
throw new RuntimeException("Nest level too deep");
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Nest level too deep : " + mNestLevel);
|
|
||||||
}
|
}
|
||||||
|
Log.e(TAG, "Nest level too deep : " + mNestLevel);
|
||||||
}
|
}
|
||||||
if (DEBUG_BATCH_NESTING) checkBatchEdit();
|
if (DEBUG_BATCH_NESTING) checkBatchEdit();
|
||||||
if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
|
if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
|
||||||
|
@ -351,10 +348,9 @@ public final class RichInputConnection implements PrivateCommandPerformer {
|
||||||
// If we have some composing text and a space before, then we should have
|
// If we have some composing text and a space before, then we should have
|
||||||
// MODE_CHARACTERS and MODE_WORDS on.
|
// MODE_CHARACTERS and MODE_WORDS on.
|
||||||
return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & inputType;
|
return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & inputType;
|
||||||
} else {
|
|
||||||
// We have some composing text - we should be in MODE_CHARACTERS only.
|
|
||||||
return TextUtils.CAP_MODE_CHARACTERS & inputType;
|
|
||||||
}
|
}
|
||||||
|
// We have some composing text - we should be in MODE_CHARACTERS only.
|
||||||
|
return TextUtils.CAP_MODE_CHARACTERS & inputType;
|
||||||
}
|
}
|
||||||
// TODO: this will generally work, but there may be cases where the buffer contains SOME
|
// TODO: this will generally work, but there may be cases where the buffer contains SOME
|
||||||
// information but not enough to determine the caps mode accurately. This may happen after
|
// information but not enough to determine the caps mode accurately. This may happen after
|
||||||
|
@ -624,10 +620,6 @@ public final class RichInputConnection implements PrivateCommandPerformer {
|
||||||
prev, spacingAndPunctuations, n);
|
prev, spacingAndPunctuations, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isSeparator(final int code, final int[] sortedSeparators) {
|
|
||||||
return Arrays.binarySearch(sortedSeparators, code) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isPartOfCompositionForScript(final int codePoint,
|
private static boolean isPartOfCompositionForScript(final int codePoint,
|
||||||
final SpacingAndPunctuations spacingAndPunctuations, final int scriptId) {
|
final SpacingAndPunctuations spacingAndPunctuations, final int scriptId) {
|
||||||
// We always consider word connectors part of compositions.
|
// We always consider word connectors part of compositions.
|
||||||
|
@ -977,7 +969,8 @@ public final class RichInputConnection implements PrivateCommandPerformer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {@code true} if the application reported that the monitor mode of
|
* @return {@code true} if the application reported that the monitor mode of
|
||||||
* {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)} is currently enabled.
|
* {@link InputMethodService#onUpdateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo)}
|
||||||
|
* is currently enabled.
|
||||||
*/
|
*/
|
||||||
public boolean isCursorAnchorInfoMonitorEnabled() {
|
public boolean isCursorAnchorInfoMonitorEnabled() {
|
||||||
return mCursorAnchorInfoMonitorEnabled;
|
return mCursorAnchorInfoMonitorEnabled;
|
||||||
|
|
|
@ -20,7 +20,6 @@ import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
|
|
@ -291,8 +291,9 @@ public final class SubtypeSwitcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RichInputMethodSubtype sForcedSubtypeForTesting = null;
|
private static RichInputMethodSubtype sForcedSubtypeForTesting = null;
|
||||||
|
|
||||||
@UsedForTesting
|
@UsedForTesting
|
||||||
void forceSubtype(final InputMethodSubtype subtype) {
|
static void forceSubtype(final InputMethodSubtype subtype) {
|
||||||
sForcedSubtypeForTesting = new RichInputMethodSubtype(subtype);
|
sForcedSubtypeForTesting = new RichInputMethodSubtype(subtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -328,7 +328,7 @@ public final class Suggest {
|
||||||
* @param info the suggestion info
|
* @param info the suggestion info
|
||||||
* @return whether it's fine to auto-correct to this.
|
* @return whether it's fine to auto-correct to this.
|
||||||
*/
|
*/
|
||||||
private boolean isAllowedByAutoCorrectionWithSpaceFilter(final SuggestedWordInfo info) {
|
private static boolean isAllowedByAutoCorrectionWithSpaceFilter(final SuggestedWordInfo info) {
|
||||||
final Locale locale = info.mSourceDict.mLocale;
|
final Locale locale = info.mSourceDict.mLocale;
|
||||||
if (null == locale) {
|
if (null == locale) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -365,9 +365,8 @@ public class SuggestedWords {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (TextUtils.isEmpty(mDebugString)) {
|
if (TextUtils.isEmpty(mDebugString)) {
|
||||||
return mWord;
|
return mWord;
|
||||||
} else {
|
|
||||||
return mWord + " (" + mDebugString + ")";
|
|
||||||
}
|
}
|
||||||
|
return mWord + " (" + mDebugString + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will always remove the higher index if a duplicate is found.
|
// This will always remove the higher index if a duplicate is found.
|
||||||
|
|
|
@ -64,7 +64,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
|
||||||
private static final String NAME = "userunigram";
|
private static final String NAME = "userunigram";
|
||||||
|
|
||||||
private ContentObserver mObserver;
|
private ContentObserver mObserver;
|
||||||
final private String mLocale;
|
final private String mLocaleString;
|
||||||
final private boolean mAlsoUseMoreRestrictiveLocales;
|
final private boolean mAlsoUseMoreRestrictiveLocales;
|
||||||
|
|
||||||
protected UserBinaryDictionary(final Context context, final Locale locale,
|
protected UserBinaryDictionary(final Context context, final Locale locale,
|
||||||
|
@ -74,9 +74,9 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
|
||||||
final String localeStr = locale.toString();
|
final String localeStr = locale.toString();
|
||||||
if (SubtypeLocaleUtils.NO_LANGUAGE.equals(localeStr)) {
|
if (SubtypeLocaleUtils.NO_LANGUAGE.equals(localeStr)) {
|
||||||
// If we don't have a locale, insert into the "all locales" user dictionary.
|
// If we don't have a locale, insert into the "all locales" user dictionary.
|
||||||
mLocale = USER_DICTIONARY_ALL_LANGUAGES;
|
mLocaleString = USER_DICTIONARY_ALL_LANGUAGES;
|
||||||
} else {
|
} else {
|
||||||
mLocale = localeStr;
|
mLocaleString = localeStr;
|
||||||
}
|
}
|
||||||
mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales;
|
mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales;
|
||||||
ContentResolver cres = context.getContentResolver();
|
ContentResolver cres = context.getContentResolver();
|
||||||
|
@ -124,7 +124,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
|
||||||
// This is correct for locale processing.
|
// This is correct for locale processing.
|
||||||
// For this example, we'll look at the "en_US_POSIX" case.
|
// For this example, we'll look at the "en_US_POSIX" case.
|
||||||
final String[] localeElements =
|
final String[] localeElements =
|
||||||
TextUtils.isEmpty(mLocale) ? new String[] {} : mLocale.split("_", 3);
|
TextUtils.isEmpty(mLocaleString) ? new String[] {} : mLocaleString.split("_", 3);
|
||||||
final int length = localeElements.length;
|
final int length = localeElements.length;
|
||||||
|
|
||||||
final StringBuilder request = new StringBuilder("(locale is NULL)");
|
final StringBuilder request = new StringBuilder("(locale is NULL)");
|
||||||
|
@ -207,9 +207,8 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
|
||||||
if (client != null) {
|
if (client != null) {
|
||||||
client.release();
|
client.release();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -227,17 +226,16 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
|
||||||
HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY, null, locale);
|
HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY, null, locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int scaleFrequencyFromDefaultToLatinIme(final int defaultFrequency) {
|
private static int scaleFrequencyFromDefaultToLatinIme(final int defaultFrequency) {
|
||||||
// The default frequency for the user dictionary is 250 for historical reasons.
|
// The default frequency for the user dictionary is 250 for historical reasons.
|
||||||
// Latin IME considers a good value for the default user dictionary frequency
|
// Latin IME considers a good value for the default user dictionary frequency
|
||||||
// is about 160 considering the scale we use. So we are scaling down the values.
|
// is about 160 considering the scale we use. So we are scaling down the values.
|
||||||
if (defaultFrequency > Integer.MAX_VALUE / LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY) {
|
if (defaultFrequency > Integer.MAX_VALUE / LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY) {
|
||||||
return (defaultFrequency / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY)
|
return (defaultFrequency / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY)
|
||||||
* LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY;
|
* LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY;
|
||||||
} else {
|
|
||||||
return (defaultFrequency * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY)
|
|
||||||
/ HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY;
|
|
||||||
}
|
}
|
||||||
|
return (defaultFrequency * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY)
|
||||||
|
/ HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addWordsLocked(final Cursor cursor) {
|
private void addWordsLocked(final Cursor cursor) {
|
||||||
|
|
|
@ -353,9 +353,8 @@ public final class WordComposer {
|
||||||
if (size() <= 1) {
|
if (size() <= 1) {
|
||||||
return mCapitalizedMode == CAPS_MODE_AUTO_SHIFT_LOCKED
|
return mCapitalizedMode == CAPS_MODE_AUTO_SHIFT_LOCKED
|
||||||
|| mCapitalizedMode == CAPS_MODE_MANUAL_SHIFT_LOCKED;
|
|| mCapitalizedMode == CAPS_MODE_MANUAL_SHIFT_LOCKED;
|
||||||
} else {
|
|
||||||
return mCapsCount == size();
|
|
||||||
}
|
}
|
||||||
|
return mCapsCount == size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean wasShiftedNoLock() {
|
public boolean wasShiftedNoLock() {
|
||||||
|
|
|
@ -44,7 +44,7 @@ import java.util.Locale;
|
||||||
* A class to read a local file as a dictionary for debugging purposes.
|
* A class to read a local file as a dictionary for debugging purposes.
|
||||||
*/
|
*/
|
||||||
public class ExternalDictionaryGetterForDebug {
|
public class ExternalDictionaryGetterForDebug {
|
||||||
private static final String SOURCE_FOLDER = Environment.getExternalStorageDirectory().getPath()
|
static final String SOURCE_FOLDER = Environment.getExternalStorageDirectory().getPath()
|
||||||
+ "/Download";
|
+ "/Download";
|
||||||
|
|
||||||
private static String[] findDictionariesInTheDownloadedFolder() {
|
private static String[] findDictionariesInTheDownloadedFolder() {
|
||||||
|
@ -142,8 +142,7 @@ public class ExternalDictionaryGetterForDebug {
|
||||||
}).create().show();
|
}).create().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void installFile(final Context context, final File file,
|
static void installFile(final Context context, final File file, final DictionaryHeader header) {
|
||||||
final DictionaryHeader header) {
|
|
||||||
BufferedOutputStream outputStream = null;
|
BufferedOutputStream outputStream = null;
|
||||||
File tempFile = null;
|
File tempFile = null;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -75,7 +75,7 @@ public final class InputLogic {
|
||||||
private static final String TAG = InputLogic.class.getSimpleName();
|
private static final String TAG = InputLogic.class.getSimpleName();
|
||||||
|
|
||||||
// TODO : Remove this member when we can.
|
// TODO : Remove this member when we can.
|
||||||
private final LatinIME mLatinIME;
|
final LatinIME mLatinIME;
|
||||||
private final SuggestionStripViewAccessor mSuggestionStripViewAccessor;
|
private final SuggestionStripViewAccessor mSuggestionStripViewAccessor;
|
||||||
|
|
||||||
// Never null.
|
// Never null.
|
||||||
|
@ -1512,12 +1512,6 @@ public final class InputLogic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final int[] codePoints = StringUtils.toCodePointArray(typedWord);
|
final int[] codePoints = StringUtils.toCodePointArray(typedWord);
|
||||||
// We want the context of preceding words for suggestion. If we have chars in the word
|
|
||||||
// before the cursor, then we want the word before that, hence 2; otherwise,
|
|
||||||
// we want the word immediately before the cursor, hence 1.
|
|
||||||
final NgramContext ngramContext = getNgramContextFromNthPreviousWordForSuggestion(
|
|
||||||
settingsValues.mSpacingAndPunctuations,
|
|
||||||
0 == numberOfCharsInWordBeforeCursor ? 1 : 2);
|
|
||||||
mWordComposer.setComposingWord(codePoints,
|
mWordComposer.setComposingWord(codePoints,
|
||||||
mLatinIME.getCoordinatesForCurrentKeyboard(codePoints));
|
mLatinIME.getCoordinatesForCurrentKeyboard(codePoints));
|
||||||
mWordComposer.setCursorPositionWithinWord(
|
mWordComposer.setCursorPositionWithinWord(
|
||||||
|
@ -1533,8 +1527,7 @@ public final class InputLogic {
|
||||||
SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {
|
SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
|
public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
|
||||||
mIsAutoCorrectionIndicatorOn = false;
|
doShowSuggestionsAndClearAutoCorrectionIndicator(suggestedWords);
|
||||||
mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
|
|
||||||
}});
|
}});
|
||||||
} else {
|
} else {
|
||||||
// We found suggestion spans in the word. We'll create the SuggestedWords out of
|
// We found suggestion spans in the word. We'll create the SuggestedWords out of
|
||||||
|
@ -1545,11 +1538,15 @@ public final class InputLogic {
|
||||||
null /* rawSuggestions */, typedWord, false /* typedWordValid */,
|
null /* rawSuggestions */, typedWord, false /* typedWordValid */,
|
||||||
false /* willAutoCorrect */, false /* isObsoleteSuggestions */,
|
false /* willAutoCorrect */, false /* isObsoleteSuggestions */,
|
||||||
SuggestedWords.INPUT_STYLE_RECORRECTION, SuggestedWords.NOT_A_SEQUENCE_NUMBER);
|
SuggestedWords.INPUT_STYLE_RECORRECTION, SuggestedWords.NOT_A_SEQUENCE_NUMBER);
|
||||||
mIsAutoCorrectionIndicatorOn = false;
|
doShowSuggestionsAndClearAutoCorrectionIndicator(suggestedWords);
|
||||||
mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void doShowSuggestionsAndClearAutoCorrectionIndicator(final SuggestedWords suggestedWords) {
|
||||||
|
mIsAutoCorrectionIndicatorOn = false;
|
||||||
|
mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverts a previous commit with auto-correction.
|
* Reverts a previous commit with auto-correction.
|
||||||
*
|
*
|
||||||
|
@ -1761,12 +1758,12 @@ public final class InputLogic {
|
||||||
// word information from textview.
|
// word information from textview.
|
||||||
return mConnection.getNgramContextFromNthPreviousWord(
|
return mConnection.getNgramContextFromNthPreviousWord(
|
||||||
spacingAndPunctuations, nthPreviousWord);
|
spacingAndPunctuations, nthPreviousWord);
|
||||||
} else {
|
|
||||||
return LastComposedWord.NOT_A_COMPOSED_WORD == mLastComposedWord ?
|
|
||||||
NgramContext.BEGINNING_OF_SENTENCE :
|
|
||||||
new NgramContext(new NgramContext.WordInfo(
|
|
||||||
mLastComposedWord.mCommittedWord.toString()));
|
|
||||||
}
|
}
|
||||||
|
if (LastComposedWord.NOT_A_COMPOSED_WORD == mLastComposedWord) {
|
||||||
|
return NgramContext.BEGINNING_OF_SENTENCE;
|
||||||
|
}
|
||||||
|
return new NgramContext(new NgramContext.WordInfo(
|
||||||
|
mLastComposedWord.mCommittedWord.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1819,9 +1816,8 @@ public final class InputLogic {
|
||||||
// If no code point, #getCodePointBeforeCursor returns NOT_A_CODE_POINT.
|
// If no code point, #getCodePointBeforeCursor returns NOT_A_CODE_POINT.
|
||||||
if (Constants.CODE_PERIOD == codePointBeforeCursor) {
|
if (Constants.CODE_PERIOD == codePointBeforeCursor) {
|
||||||
return text.substring(1);
|
return text.substring(1);
|
||||||
} else {
|
|
||||||
return text;
|
|
||||||
}
|
}
|
||||||
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1877,7 +1873,7 @@ public final class InputLogic {
|
||||||
* @param previousSuggestedWords The previously suggested words.
|
* @param previousSuggestedWords The previously suggested words.
|
||||||
* @return Obsolete suggestions with the newly typed word.
|
* @return Obsolete suggestions with the newly typed word.
|
||||||
*/
|
*/
|
||||||
private SuggestedWords retrieveOlderSuggestions(final String typedWord,
|
static SuggestedWords retrieveOlderSuggestions(final String typedWord,
|
||||||
final SuggestedWords previousSuggestedWords) {
|
final SuggestedWords previousSuggestedWords) {
|
||||||
final SuggestedWords oldSuggestedWords = previousSuggestedWords.isPunctuationSuggestions()
|
final SuggestedWords oldSuggestedWords = previousSuggestedWords.isPunctuationSuggestions()
|
||||||
? SuggestedWords.getEmptyInstance() : previousSuggestedWords;
|
? SuggestedWords.getEmptyInstance() : previousSuggestedWords;
|
||||||
|
|
|
@ -23,7 +23,6 @@ import android.os.Message;
|
||||||
import com.android.inputmethod.compat.LooperCompatUtils;
|
import com.android.inputmethod.compat.LooperCompatUtils;
|
||||||
import com.android.inputmethod.latin.InputPointers;
|
import com.android.inputmethod.latin.InputPointers;
|
||||||
import com.android.inputmethod.latin.LatinIME;
|
import com.android.inputmethod.latin.LatinIME;
|
||||||
import com.android.inputmethod.latin.Suggest;
|
|
||||||
import com.android.inputmethod.latin.SuggestedWords;
|
import com.android.inputmethod.latin.SuggestedWords;
|
||||||
import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
|
import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
|
||||||
|
|
||||||
|
@ -62,7 +61,7 @@ class InputLogicHandler implements Handler.Callback {
|
||||||
final OnGetSuggestedWordsCallback callback) {}
|
final OnGetSuggestedWordsCallback callback) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
private InputLogicHandler() {
|
InputLogicHandler() {
|
||||||
mNonUIThreadHandler = null;
|
mNonUIThreadHandler = null;
|
||||||
mLatinIME = null;
|
mLatinIME = null;
|
||||||
mInputLogic = null;
|
mInputLogic = null;
|
||||||
|
@ -134,30 +133,38 @@ class InputLogicHandler implements Handler.Callback {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mInputLogic.mWordComposer.setBatchInputPointers(batchPointers);
|
mInputLogic.mWordComposer.setBatchInputPointers(batchPointers);
|
||||||
|
final OnGetSuggestedWordsCallback callback = new OnGetSuggestedWordsCallback() {
|
||||||
|
@Override
|
||||||
|
public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
|
||||||
|
showGestureSuggestionsWithPreviewVisuals(suggestedWords, isTailBatchInput);
|
||||||
|
}
|
||||||
|
};
|
||||||
getSuggestedWords(isTailBatchInput ? SuggestedWords.INPUT_STYLE_TAIL_BATCH
|
getSuggestedWords(isTailBatchInput ? SuggestedWords.INPUT_STYLE_TAIL_BATCH
|
||||||
: SuggestedWords.INPUT_STYLE_UPDATE_BATCH, sequenceNumber,
|
: SuggestedWords.INPUT_STYLE_UPDATE_BATCH, sequenceNumber, callback);
|
||||||
new OnGetSuggestedWordsCallback() {
|
}
|
||||||
@Override
|
}
|
||||||
public void onGetSuggestedWords(SuggestedWords suggestedWords) {
|
|
||||||
// We're now inside the callback. This always runs on the Non-UI thread,
|
void showGestureSuggestionsWithPreviewVisuals(final SuggestedWords suggestedWordsForBatchInput,
|
||||||
// no matter what thread updateBatchInput was originally called on.
|
final boolean isTailBatchInput) {
|
||||||
if (suggestedWords.isEmpty()) {
|
final SuggestedWords suggestedWordsToShowSuggestions;
|
||||||
// Use old suggestions if we don't have any new ones.
|
// We're now inside the callback. This always runs on the Non-UI thread,
|
||||||
// Previous suggestions are found in InputLogic#mSuggestedWords.
|
// no matter what thread updateBatchInput was originally called on.
|
||||||
// Since these are the most recent ones and we just recomputed
|
if (suggestedWordsForBatchInput.isEmpty()) {
|
||||||
// new ones to update them, then the previous ones are there.
|
// Use old suggestions if we don't have any new ones.
|
||||||
suggestedWords = mInputLogic.mSuggestedWords;
|
// Previous suggestions are found in InputLogic#mSuggestedWords.
|
||||||
}
|
// Since these are the most recent ones and we just recomputed
|
||||||
mLatinIME.mHandler.showGesturePreviewAndSuggestionStrip(suggestedWords,
|
// new ones to update them, then the previous ones are there.
|
||||||
isTailBatchInput /* dismissGestureFloatingPreviewText */);
|
suggestedWordsToShowSuggestions = mInputLogic.mSuggestedWords;
|
||||||
if (isTailBatchInput) {
|
} else {
|
||||||
mInBatchInput = false;
|
suggestedWordsToShowSuggestions = suggestedWordsForBatchInput;
|
||||||
// The following call schedules onEndBatchInputInternal
|
}
|
||||||
// to be called on the UI thread.
|
mLatinIME.mHandler.showGesturePreviewAndSuggestionStrip(suggestedWordsToShowSuggestions,
|
||||||
mLatinIME.mHandler.showTailBatchInputResult(suggestedWords);
|
isTailBatchInput /* dismissGestureFloatingPreviewText */);
|
||||||
}
|
if (isTailBatchInput) {
|
||||||
}
|
mInBatchInput = false;
|
||||||
});
|
// The following call schedules onEndBatchInputInternal
|
||||||
|
// to be called on the UI thread.
|
||||||
|
mLatinIME.mHandler.showTailBatchInputResult(suggestedWordsToShowSuggestions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,11 +40,8 @@ public final class ProbabilityInfo {
|
||||||
if (probabilityInfo2 == null) {
|
if (probabilityInfo2 == null) {
|
||||||
return probabilityInfo1;
|
return probabilityInfo1;
|
||||||
}
|
}
|
||||||
if (probabilityInfo1.mProbability > probabilityInfo2.mProbability) {
|
return (probabilityInfo1.mProbability > probabilityInfo2.mProbability) ? probabilityInfo1
|
||||||
return probabilityInfo1;
|
: probabilityInfo2;
|
||||||
} else {
|
|
||||||
return probabilityInfo2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProbabilityInfo(final int probability) {
|
public ProbabilityInfo(final int probability) {
|
||||||
|
@ -67,9 +64,8 @@ public final class ProbabilityInfo {
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
if (hasHistoricalInfo()) {
|
if (hasHistoricalInfo()) {
|
||||||
return Arrays.hashCode(new Object[] { mProbability, mTimestamp, mLevel, mCount });
|
return Arrays.hashCode(new Object[] { mProbability, mTimestamp, mLevel, mCount });
|
||||||
} else {
|
|
||||||
return Arrays.hashCode(new Object[] { mProbability });
|
|
||||||
}
|
}
|
||||||
|
return Arrays.hashCode(new Object[] { mProbability });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -18,6 +18,7 @@ package com.android.inputmethod.latin.makedict;
|
||||||
|
|
||||||
import com.android.inputmethod.annotations.UsedForTesting;
|
import com.android.inputmethod.annotations.UsedForTesting;
|
||||||
import com.android.inputmethod.latin.BinaryDictionary;
|
import com.android.inputmethod.latin.BinaryDictionary;
|
||||||
|
import com.android.inputmethod.latin.Dictionary;
|
||||||
import com.android.inputmethod.latin.NgramContext;
|
import com.android.inputmethod.latin.NgramContext;
|
||||||
import com.android.inputmethod.latin.NgramContext.WordInfo;
|
import com.android.inputmethod.latin.NgramContext.WordInfo;
|
||||||
import com.android.inputmethod.latin.utils.CombinedFormatUtils;
|
import com.android.inputmethod.latin.utils.CombinedFormatUtils;
|
||||||
|
@ -61,10 +62,8 @@ public final class WordProperty implements Comparable<WordProperty> {
|
||||||
} else {
|
} else {
|
||||||
mNgrams = new ArrayList<>();
|
mNgrams = new ArrayList<>();
|
||||||
final NgramContext ngramContext = new NgramContext(new WordInfo(mWord));
|
final NgramContext ngramContext = new NgramContext(new WordInfo(mWord));
|
||||||
if (bigrams != null) {
|
for (final WeightedString bigramTarget : bigrams) {
|
||||||
for (final WeightedString bigramTarget : bigrams) {
|
mNgrams.add(new NgramProperty(bigramTarget, ngramContext));
|
||||||
mNgrams.add(new NgramProperty(bigramTarget, ngramContext));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mIsBeginningOfSentence = false;
|
mIsBeginningOfSentence = false;
|
||||||
|
@ -104,7 +103,8 @@ public final class WordProperty implements Comparable<WordProperty> {
|
||||||
|
|
||||||
final int relatedNgramCount = ngramTargets.size();
|
final int relatedNgramCount = ngramTargets.size();
|
||||||
final WordInfo currentWordInfo =
|
final WordInfo currentWordInfo =
|
||||||
mIsBeginningOfSentence ? WordInfo.BEGINNING_OF_SENTENCE : new WordInfo(mWord);
|
mIsBeginningOfSentence ? WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO
|
||||||
|
: new WordInfo(mWord);
|
||||||
final NgramContext ngramContext = new NgramContext(currentWordInfo);
|
final NgramContext ngramContext = new NgramContext(currentWordInfo);
|
||||||
for (int i = 0; i < relatedNgramCount; i++) {
|
for (int i = 0; i < relatedNgramCount; i++) {
|
||||||
final String ngramTargetString =
|
final String ngramTargetString =
|
||||||
|
@ -202,7 +202,7 @@ public final class WordProperty implements Comparable<WordProperty> {
|
||||||
|
|
||||||
@UsedForTesting
|
@UsedForTesting
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return getProbability() != BinaryDictionary.NOT_A_PROBABILITY;
|
return getProbability() != Dictionary.NOT_A_PROBABILITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -85,12 +85,11 @@ public class BlockingHttpClient {
|
||||||
throw new AuthException(mConnection.getResponseMessage());
|
throw new AuthException(mConnection.getResponseMessage());
|
||||||
}
|
}
|
||||||
throw new HttpException(responseCode);
|
throw new HttpException(responseCode);
|
||||||
} else {
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d(TAG, "request executed successfully");
|
|
||||||
}
|
|
||||||
return responseProcessor.onSuccess(mConnection.getInputStream());
|
|
||||||
}
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "request executed successfully");
|
||||||
|
}
|
||||||
|
return responseProcessor.onSuccess(mConnection.getInputStream());
|
||||||
} finally {
|
} finally {
|
||||||
mConnection.disconnect();
|
mConnection.disconnect();
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,14 +39,10 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
|
||||||
public static final int FREQUENCY_FOR_WORDS_IN_DICTS = FREQUENCY_FOR_TYPED;
|
public static final int FREQUENCY_FOR_WORDS_IN_DICTS = FREQUENCY_FOR_TYPED;
|
||||||
public static final int FREQUENCY_FOR_WORDS_NOT_IN_DICTS = Dictionary.NOT_A_PROBABILITY;
|
public static final int FREQUENCY_FOR_WORDS_NOT_IN_DICTS = Dictionary.NOT_A_PROBABILITY;
|
||||||
|
|
||||||
/** The locale for this dictionary. */
|
|
||||||
public final Locale mLocale;
|
|
||||||
|
|
||||||
protected DecayingExpandableBinaryDictionaryBase(final Context context,
|
protected DecayingExpandableBinaryDictionaryBase(final Context context,
|
||||||
final String dictName, final Locale locale, final String dictionaryType,
|
final String dictName, final Locale locale, final String dictionaryType,
|
||||||
final File dictFile) {
|
final File dictFile) {
|
||||||
super(context, dictName, locale, dictionaryType, dictFile);
|
super(context, dictName, locale, dictionaryType, dictFile);
|
||||||
mLocale = locale;
|
|
||||||
if (mLocale != null && mLocale.toString().length() > 1) {
|
if (mLocale != null && mLocale.toString().length() > 1) {
|
||||||
reloadDictionaryIfRequired();
|
reloadDictionaryIfRequired();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package com.android.inputmethod.latin.personalization;
|
package com.android.inputmethod.latin.personalization;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import com.android.inputmethod.annotations.UsedForTesting;
|
import com.android.inputmethod.annotations.UsedForTesting;
|
||||||
import com.android.inputmethod.latin.Constants;
|
import com.android.inputmethod.latin.Constants;
|
||||||
|
@ -35,7 +34,6 @@ import java.util.Locale;
|
||||||
*/
|
*/
|
||||||
public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase {
|
public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase {
|
||||||
/* package */ static final String NAME = UserHistoryDictionary.class.getSimpleName();
|
/* package */ static final String NAME = UserHistoryDictionary.class.getSimpleName();
|
||||||
private final static int SUPPORTED_NGRAM = 2; // TODO: 3
|
|
||||||
|
|
||||||
// TODO: Make this constructor private
|
// TODO: Make this constructor private
|
||||||
/* package */ UserHistoryDictionary(final Context context, final Locale locale) {
|
/* package */ UserHistoryDictionary(final Context context, final Locale locale) {
|
||||||
|
|
|
@ -259,6 +259,7 @@ final class CustomInputStylePreference extends DialogPreference
|
||||||
mSubtype = (InputMethodSubtype)source.readParcelable(null);
|
mSubtype = (InputMethodSubtype)source.readParcelable(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("hiding")
|
||||||
public static final Parcelable.Creator<SavedState> CREATOR =
|
public static final Parcelable.Creator<SavedState> CREATOR =
|
||||||
new Parcelable.Creator<SavedState>() {
|
new Parcelable.Creator<SavedState>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin.settings;
|
package com.android.inputmethod.latin.settings;
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
|
|
|
@ -20,8 +20,6 @@ import android.os.Bundle;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Multilingual options" settings sub screen.
|
* "Multilingual options" settings sub screen.
|
||||||
*
|
*
|
||||||
|
|
|
@ -43,9 +43,7 @@ public class RadioButtonPreference extends Preference {
|
||||||
private final View.OnClickListener mClickListener = new View.OnClickListener() {
|
private final View.OnClickListener mClickListener = new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(final View v) {
|
public void onClick(final View v) {
|
||||||
if (mListener != null) {
|
callListenerOnRadioButtonClicked();
|
||||||
mListener.onRadioButtonClicked(RadioButtonPreference.this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,6 +65,12 @@ public class RadioButtonPreference extends Preference {
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void callListenerOnRadioButtonClicked() {
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onRadioButtonClicked(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onBindView(final View view) {
|
protected void onBindView(final View view) {
|
||||||
super.onBindView(view);
|
super.onBindView(view);
|
||||||
|
|
|
@ -273,9 +273,8 @@ public class SettingsValues {
|
||||||
final RichInputMethodManager imm = RichInputMethodManager.getInstance();
|
final RichInputMethodManager imm = RichInputMethodManager.getInstance();
|
||||||
if (mIncludesOtherImesInLanguageSwitchList) {
|
if (mIncludesOtherImesInLanguageSwitchList) {
|
||||||
return imm.hasMultipleEnabledIMEsOrSubtypes(false /* include aux subtypes */);
|
return imm.hasMultipleEnabledIMEsOrSubtypes(false /* include aux subtypes */);
|
||||||
} else {
|
|
||||||
return imm.hasMultipleEnabledSubtypesInThisIme(false /* include aux subtypes */);
|
|
||||||
}
|
}
|
||||||
|
return imm.hasMultipleEnabledSubtypesInThisIme(false /* include aux subtypes */);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSameInputType(final EditorInfo editorInfo) {
|
public boolean isSameInputType(final EditorInfo editorInfo) {
|
||||||
|
|
|
@ -50,9 +50,6 @@ import java.util.concurrent.Semaphore;
|
||||||
*/
|
*/
|
||||||
public final class AndroidSpellCheckerService extends SpellCheckerService
|
public final class AndroidSpellCheckerService extends SpellCheckerService
|
||||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
private static final String TAG = AndroidSpellCheckerService.class.getSimpleName();
|
|
||||||
private static final boolean DBG = false;
|
|
||||||
|
|
||||||
public static final String PREF_USE_CONTACTS_KEY = "pref_spellcheck_use_contacts";
|
public static final String PREF_USE_CONTACTS_KEY = "pref_spellcheck_use_contacts";
|
||||||
|
|
||||||
private static final int SPELLCHECKER_DUMMY_KEYBOARD_WIDTH = 480;
|
private static final int SPELLCHECKER_DUMMY_KEYBOARD_WIDTH = 480;
|
||||||
|
|
|
@ -312,11 +312,10 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
|
||||||
// Don't kill the keyboard if there is a bug in the spell checker
|
// Don't kill the keyboard if there is a bug in the spell checker
|
||||||
if (DBG) {
|
if (DBG) {
|
||||||
throw e;
|
throw e;
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Exception while spellcheking", e);
|
|
||||||
return AndroidSpellCheckerService.getNotInDictEmptySuggestions(
|
|
||||||
false /* reportAsTypo */);
|
|
||||||
}
|
}
|
||||||
|
Log.e(TAG, "Exception while spellcheking", e);
|
||||||
|
return AndroidSpellCheckerService.getNotInDictEmptySuggestions(
|
||||||
|
false /* reportAsTypo */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,9 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin.spellcheck;
|
package com.android.inputmethod.latin.spellcheck;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.os.Build;
|
||||||
import android.view.textservice.SentenceSuggestionsInfo;
|
import android.view.textservice.SentenceSuggestionsInfo;
|
||||||
import android.view.textservice.SuggestionsInfo;
|
import android.view.textservice.SuggestionsInfo;
|
||||||
import android.view.textservice.TextInfo;
|
import android.view.textservice.TextInfo;
|
||||||
|
@ -76,19 +78,19 @@ public class SentenceLevelAdapter {
|
||||||
private static class WordIterator {
|
private static class WordIterator {
|
||||||
private final SpacingAndPunctuations mSpacingAndPunctuations;
|
private final SpacingAndPunctuations mSpacingAndPunctuations;
|
||||||
public WordIterator(final Resources res, final Locale locale) {
|
public WordIterator(final Resources res, final Locale locale) {
|
||||||
final RunInLocale<SpacingAndPunctuations> job
|
final RunInLocale<SpacingAndPunctuations> job =
|
||||||
= new RunInLocale<SpacingAndPunctuations>() {
|
new RunInLocale<SpacingAndPunctuations>() {
|
||||||
@Override
|
@Override
|
||||||
protected SpacingAndPunctuations job(final Resources res) {
|
protected SpacingAndPunctuations job(final Resources r) {
|
||||||
return new SpacingAndPunctuations(res);
|
return new SpacingAndPunctuations(r);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mSpacingAndPunctuations = job.runInLocale(res, locale);
|
mSpacingAndPunctuations = job.runInLocale(res, locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getEndOfWord(final CharSequence sequence, int index) {
|
public int getEndOfWord(final CharSequence sequence, final int fromIndex) {
|
||||||
final int length = sequence.length();
|
final int length = sequence.length();
|
||||||
index = index < 0 ? 0 : Character.offsetByCodePoints(sequence, index, 1);
|
int index = fromIndex < 0 ? 0 : Character.offsetByCodePoints(sequence, fromIndex, 1);
|
||||||
while (index < length) {
|
while (index < length) {
|
||||||
final int codePoint = Character.codePointAt(sequence, index);
|
final int codePoint = Character.codePointAt(sequence, index);
|
||||||
if (mSpacingAndPunctuations.isWordSeparator(codePoint)) {
|
if (mSpacingAndPunctuations.isWordSeparator(codePoint)) {
|
||||||
|
@ -111,12 +113,12 @@ public class SentenceLevelAdapter {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getBeginningOfNextWord(final CharSequence sequence, int index) {
|
public int getBeginningOfNextWord(final CharSequence sequence, final int fromIndex) {
|
||||||
final int length = sequence.length();
|
final int length = sequence.length();
|
||||||
if (index >= length) {
|
if (fromIndex >= length) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
index = index < 0 ? 0 : Character.offsetByCodePoints(sequence, index, 1);
|
int index = fromIndex < 0 ? 0 : Character.offsetByCodePoints(sequence, fromIndex, 1);
|
||||||
while (index < length) {
|
while (index < length) {
|
||||||
final int codePoint = Character.codePointAt(sequence, index);
|
final int codePoint = Character.codePointAt(sequence, index);
|
||||||
if (!mSpacingAndPunctuations.isWordSeparator(codePoint)) {
|
if (!mSpacingAndPunctuations.isWordSeparator(codePoint)) {
|
||||||
|
@ -140,7 +142,7 @@ public class SentenceLevelAdapter {
|
||||||
final int cookie = originalTextInfo.getCookie();
|
final int cookie = originalTextInfo.getCookie();
|
||||||
final int start = -1;
|
final int start = -1;
|
||||||
final int end = originalText.length();
|
final int end = originalText.length();
|
||||||
final ArrayList<SentenceWordItem> wordItems = new ArrayList<SentenceWordItem>();
|
final ArrayList<SentenceWordItem> wordItems = new ArrayList<>();
|
||||||
int wordStart = wordIterator.getBeginningOfNextWord(originalText, start);
|
int wordStart = wordIterator.getBeginningOfNextWord(originalText, start);
|
||||||
int wordEnd = wordIterator.getEndOfWord(originalText, wordStart);
|
int wordEnd = wordIterator.getEndOfWord(originalText, wordStart);
|
||||||
while (wordStart <= end && wordEnd != -1 && wordStart != -1) {
|
while (wordStart <= end && wordEnd != -1 && wordStart != -1) {
|
||||||
|
@ -158,6 +160,7 @@ public class SentenceLevelAdapter {
|
||||||
return new SentenceTextInfoParams(originalTextInfo, wordItems);
|
return new SentenceTextInfoParams(originalTextInfo, wordItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||||
public static SentenceSuggestionsInfo reconstructSuggestions(
|
public static SentenceSuggestionsInfo reconstructSuggestions(
|
||||||
SentenceTextInfoParams originalTextInfoParams, SuggestionsInfo[] results) {
|
SentenceTextInfoParams originalTextInfoParams, SuggestionsInfo[] results) {
|
||||||
if (results == null || results.length == 0) {
|
if (results == null || results.length == 0) {
|
||||||
|
|
|
@ -50,10 +50,8 @@ import com.android.inputmethod.latin.PunctuationSuggestions;
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
import com.android.inputmethod.latin.SuggestedWords;
|
import com.android.inputmethod.latin.SuggestedWords;
|
||||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||||
import com.android.inputmethod.latin.define.DebugFlags;
|
|
||||||
import com.android.inputmethod.latin.settings.Settings;
|
import com.android.inputmethod.latin.settings.Settings;
|
||||||
import com.android.inputmethod.latin.settings.SettingsValues;
|
import com.android.inputmethod.latin.settings.SettingsValues;
|
||||||
import com.android.inputmethod.latin.utils.AutoCorrectionUtils;
|
|
||||||
import com.android.inputmethod.latin.utils.ResourceUtils;
|
import com.android.inputmethod.latin.utils.ResourceUtils;
|
||||||
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
||||||
import com.android.inputmethod.latin.utils.ViewLayoutUtils;
|
import com.android.inputmethod.latin.utils.ViewLayoutUtils;
|
||||||
|
@ -380,6 +378,7 @@ final class SuggestionStripLayoutHelper {
|
||||||
|
|
||||||
final int countInStrip = mSuggestionsCountInStrip;
|
final int countInStrip = mSuggestionsCountInStrip;
|
||||||
mMoreSuggestionsAvailable = (wordCountToShow > countInStrip);
|
mMoreSuggestionsAvailable = (wordCountToShow > countInStrip);
|
||||||
|
@SuppressWarnings("unused")
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) {
|
for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) {
|
||||||
if (positionInStrip != 0) {
|
if (positionInStrip != 0) {
|
||||||
|
|
|
@ -177,12 +177,11 @@ public class UserDictionarySettings extends ListFragment {
|
||||||
return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION,
|
return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION,
|
||||||
QUERY_SELECTION_ALL_LOCALES, null,
|
QUERY_SELECTION_ALL_LOCALES, null,
|
||||||
"UPPER(" + UserDictionary.Words.WORD + ")");
|
"UPPER(" + UserDictionary.Words.WORD + ")");
|
||||||
} else {
|
|
||||||
final String queryLocale = null != locale ? locale : Locale.getDefault().toString();
|
|
||||||
return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION,
|
|
||||||
QUERY_SELECTION, new String[] { queryLocale },
|
|
||||||
"UPPER(" + UserDictionary.Words.WORD + ")");
|
|
||||||
}
|
}
|
||||||
|
final String queryLocale = null != locale ? locale : Locale.getDefault().toString();
|
||||||
|
return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION,
|
||||||
|
QUERY_SELECTION, new String[] { queryLocale },
|
||||||
|
"UPPER(" + UserDictionary.Words.WORD + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
private ListAdapter createAdapter() {
|
private ListAdapter createAdapter() {
|
||||||
|
|
|
@ -59,11 +59,7 @@ public class AsyncResultHolder<E> {
|
||||||
*/
|
*/
|
||||||
public E get(final E defaultValue, final long timeOut) {
|
public E get(final E defaultValue, final long timeOut) {
|
||||||
try {
|
try {
|
||||||
if (mLatch.await(timeOut, TimeUnit.MILLISECONDS)) {
|
return mLatch.await(timeOut, TimeUnit.MILLISECONDS) ? mResult : defaultValue;
|
||||||
return mResult;
|
|
||||||
} else {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import com.android.inputmethod.latin.define.DebugFlags;
|
||||||
public final class AutoCorrectionUtils {
|
public final class AutoCorrectionUtils {
|
||||||
private static final boolean DBG = DebugFlags.DEBUG_ENABLED;
|
private static final boolean DBG = DebugFlags.DEBUG_ENABLED;
|
||||||
private static final String TAG = AutoCorrectionUtils.class.getSimpleName();
|
private static final String TAG = AutoCorrectionUtils.class.getSimpleName();
|
||||||
private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4;
|
|
||||||
|
|
||||||
private AutoCorrectionUtils() {
|
private AutoCorrectionUtils() {
|
||||||
// Purely static class: can't instantiate.
|
// Purely static class: can't instantiate.
|
||||||
|
|
|
@ -18,9 +18,6 @@ package com.android.inputmethod.latin.utils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
public final class CollectionUtils {
|
public final class CollectionUtils {
|
||||||
private CollectionUtils() {
|
private CollectionUtils() {
|
||||||
|
@ -47,7 +44,7 @@ public final class CollectionUtils {
|
||||||
* @param c Collection to test.
|
* @param c Collection to test.
|
||||||
* @return Whether c contains no elements.
|
* @return Whether c contains no elements.
|
||||||
*/
|
*/
|
||||||
public static boolean isNullOrEmpty(final Collection c) {
|
public static boolean isNullOrEmpty(final Collection<?> c) {
|
||||||
return c == null || c.isEmpty();
|
return c == null || c.isEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import android.inputmethodservice.InputMethodService;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.text.Layout;
|
import android.text.Layout;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
|
import android.text.Spanned;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewParent;
|
import android.view.ViewParent;
|
||||||
import android.view.inputmethod.CursorAnchorInfo;
|
import android.view.inputmethod.CursorAnchorInfo;
|
||||||
|
@ -149,7 +150,7 @@ public final class CursorAnchorInfoUtils {
|
||||||
final Object[] spans = spannable.getSpans(0, text.length(), Object.class);
|
final Object[] spans = spannable.getSpans(0, text.length(), Object.class);
|
||||||
for (Object span : spans) {
|
for (Object span : spans) {
|
||||||
final int spanFlag = spannable.getSpanFlags(span);
|
final int spanFlag = spannable.getSpanFlags(span);
|
||||||
if ((spanFlag & Spannable.SPAN_COMPOSING) != 0) {
|
if ((spanFlag & Spanned.SPAN_COMPOSING) != 0) {
|
||||||
composingTextStart = Math.min(composingTextStart,
|
composingTextStart = Math.min(composingTextStart,
|
||||||
spannable.getSpanStart(span));
|
spannable.getSpanStart(span));
|
||||||
composingTextEnd = Math.max(composingTextEnd, spannable.getSpanEnd(span));
|
composingTextEnd = Math.max(composingTextEnd, spannable.getSpanEnd(span));
|
||||||
|
|
|
@ -41,10 +41,9 @@ public class DistracterFilterCheckingIsInDictionary implements DistracterFilter
|
||||||
// This filter treats entries that are already in the dictionary as non-distracters
|
// This filter treats entries that are already in the dictionary as non-distracters
|
||||||
// because they have passed the filtering in the past.
|
// because they have passed the filtering in the past.
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
return mDistracterFilter.isDistracterToWordsInDictionaries(
|
|
||||||
ngramContext, testedWord, locale);
|
|
||||||
}
|
}
|
||||||
|
return mDistracterFilter.isDistracterToWordsInDictionaries(
|
||||||
|
ngramContext, testedWord, locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -27,7 +27,7 @@ import java.util.concurrent.ThreadFactory;
|
||||||
* Utilities to manage executors.
|
* Utilities to manage executors.
|
||||||
*/
|
*/
|
||||||
public class ExecutorUtils {
|
public class ExecutorUtils {
|
||||||
private static final ConcurrentHashMap<String, ExecutorService> sExecutorMap =
|
static final ConcurrentHashMap<String, ExecutorService> sExecutorMap =
|
||||||
new ConcurrentHashMap<>();
|
new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private static class ThreadFactoryWithId implements ThreadFactory {
|
private static class ThreadFactoryWithId implements ThreadFactory {
|
||||||
|
@ -49,7 +49,7 @@ public class ExecutorUtils {
|
||||||
public static ExecutorService getExecutor(final String id) {
|
public static ExecutorService getExecutor(final String id) {
|
||||||
ExecutorService executor = sExecutorMap.get(id);
|
ExecutorService executor = sExecutorMap.get(id);
|
||||||
if (executor == null) {
|
if (executor == null) {
|
||||||
synchronized(sExecutorMap) {
|
synchronized (sExecutorMap) {
|
||||||
executor = sExecutorMap.get(id);
|
executor = sExecutorMap.get(id);
|
||||||
if (executor == null) {
|
if (executor == null) {
|
||||||
executor = Executors.newSingleThreadExecutor(new ThreadFactoryWithId(id));
|
executor = Executors.newSingleThreadExecutor(new ThreadFactoryWithId(id));
|
||||||
|
@ -65,7 +65,7 @@ public class ExecutorUtils {
|
||||||
*/
|
*/
|
||||||
@UsedForTesting
|
@UsedForTesting
|
||||||
public static void shutdownAllExecutors() {
|
public static void shutdownAllExecutors() {
|
||||||
synchronized(sExecutorMap) {
|
synchronized (sExecutorMap) {
|
||||||
for (final ExecutorService executor : sExecutorMap.values()) {
|
for (final ExecutorService executor : sExecutorMap.values()) {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,7 +20,6 @@ import android.util.Log;
|
||||||
|
|
||||||
import com.android.inputmethod.annotations.UsedForTesting;
|
import com.android.inputmethod.annotations.UsedForTesting;
|
||||||
import com.android.inputmethod.latin.Dictionary;
|
import com.android.inputmethod.latin.Dictionary;
|
||||||
import com.android.inputmethod.latin.DictionaryFacilitator;
|
|
||||||
import com.android.inputmethod.latin.NgramContext;
|
import com.android.inputmethod.latin.NgramContext;
|
||||||
import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
|
import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
|
||||||
import com.android.inputmethod.latin.utils.DistracterFilter.HandlingType;
|
import com.android.inputmethod.latin.utils.DistracterFilter.HandlingType;
|
||||||
|
|
|
@ -74,20 +74,20 @@ public final class NgramContextUtils {
|
||||||
}
|
}
|
||||||
// If we can't find (n + i) words, the context is beginning-of-sentence.
|
// If we can't find (n + i) words, the context is beginning-of-sentence.
|
||||||
if (focusedWordIndex < 0) {
|
if (focusedWordIndex < 0) {
|
||||||
prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE;
|
prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
final String focusedWord = w[focusedWordIndex];
|
final String focusedWord = w[focusedWordIndex];
|
||||||
// If the word is, the context is beginning-of-sentence.
|
// If the word is, the context is beginning-of-sentence.
|
||||||
final int length = focusedWord.length();
|
final int length = focusedWord.length();
|
||||||
if (length <= 0) {
|
if (length <= 0) {
|
||||||
prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE;
|
prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// If ends in a sentence separator, the context is beginning-of-sentence.
|
// If ends in a sentence separator, the context is beginning-of-sentence.
|
||||||
final char lastChar = focusedWord.charAt(length - 1);
|
final char lastChar = focusedWord.charAt(length - 1);
|
||||||
if (spacingAndPunctuations.isSentenceSeparator(lastChar)) {
|
if (spacingAndPunctuations.isSentenceSeparator(lastChar)) {
|
||||||
prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE;
|
prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// If ends in a word separator or connector, the context is unclear.
|
// If ends in a word separator or connector, the context is unclear.
|
||||||
|
|
|
@ -51,7 +51,7 @@ public final class SpannableStringUtils {
|
||||||
// of a word. But the spans have been split into two by the getText{Before,After}Cursor
|
// of a word. But the spans have been split into two by the getText{Before,After}Cursor
|
||||||
// methods, so after concatenation they may end in the middle of a word.
|
// methods, so after concatenation they may end in the middle of a word.
|
||||||
// Since we don't use them, we can just remove them and avoid crashing.
|
// Since we don't use them, we can just remove them and avoid crashing.
|
||||||
fl &= ~Spannable.SPAN_PARAGRAPH;
|
fl &= ~Spanned.SPAN_PARAGRAPH;
|
||||||
|
|
||||||
int st = source.getSpanStart(spans[i]);
|
int st = source.getSpanStart(spans[i]);
|
||||||
int en = source.getSpanEnd(spans[i]);
|
int en = source.getSpanEnd(spans[i]);
|
||||||
|
|
|
@ -39,7 +39,7 @@ import java.util.Locale;
|
||||||
*/
|
*/
|
||||||
// TODO: consolidate this into RichInputMethodSubtype
|
// TODO: consolidate this into RichInputMethodSubtype
|
||||||
public final class SubtypeLocaleUtils {
|
public final class SubtypeLocaleUtils {
|
||||||
private static final String TAG = SubtypeLocaleUtils.class.getSimpleName();
|
static final String TAG = SubtypeLocaleUtils.class.getSimpleName();
|
||||||
|
|
||||||
// This reference class {@link Constants} must be located in the same package as LatinIME.java.
|
// This reference class {@link Constants} must be located in the same package as LatinIME.java.
|
||||||
private static final String RESOURCE_PACKAGE_NAME = Constants.class.getPackage().getName();
|
private static final String RESOURCE_PACKAGE_NAME = Constants.class.getPackage().getName();
|
||||||
|
@ -245,9 +245,8 @@ public final class SubtypeLocaleUtils {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
|
||||||
&& subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) {
|
&& subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) {
|
||||||
return subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME);
|
return subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME);
|
||||||
} else {
|
|
||||||
return getSubtypeLocaleDisplayNameInternal(subtype.getLocale(), displayLocale);
|
|
||||||
}
|
}
|
||||||
|
return getSubtypeLocaleDisplayNameInternal(subtype.getLocale(), displayLocale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getSubtypeDisplayNameInSystemLocale(final InputMethodSubtype subtype) {
|
public static String getSubtypeDisplayNameInSystemLocale(final InputMethodSubtype subtype) {
|
||||||
|
|
|
@ -66,8 +66,7 @@ public final class SuggestionResults extends TreeSet<SuggestedWordInfo> {
|
||||||
return super.addAll(e);
|
return super.addAll(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class SuggestedWordInfoComparator
|
static final class SuggestedWordInfoComparator implements Comparator<SuggestedWordInfo> {
|
||||||
implements Comparator<SuggestedWordInfo> {
|
|
||||||
// This comparator ranks the word info with the higher frequency first. That's because
|
// This comparator ranks the word info with the higher frequency first. That's because
|
||||||
// that's the order we want our elements in.
|
// that's the order we want our elements in.
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,7 +20,6 @@ import android.graphics.Typeface;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.test.AndroidTestCase;
|
import android.test.AndroidTestCase;
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
import android.text.Spannable;
|
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.style.StyleSpan;
|
import android.text.style.StyleSpan;
|
||||||
|
@ -72,141 +71,141 @@ public class LocaleSpanCompatUtilsTests extends AndroidTestCase {
|
||||||
final SpannableString text = new SpannableString("0123456789");
|
final SpannableString text = new SpannableString("0123456789");
|
||||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE);
|
LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE);
|
||||||
assertSpanCount(1, text);
|
assertSpanCount(1, text);
|
||||||
assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if only LocaleSpans are updated.
|
// Test if only LocaleSpans are updated.
|
||||||
{
|
{
|
||||||
final SpannableString text = new SpannableString("0123456789");
|
final SpannableString text = new SpannableString("0123456789");
|
||||||
final StyleSpan styleSpan = new StyleSpan(Typeface.BOLD);
|
final StyleSpan styleSpan = new StyleSpan(Typeface.BOLD);
|
||||||
text.setSpan(styleSpan, 0, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
text.setSpan(styleSpan, 0, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE);
|
LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE);
|
||||||
assertSpanCount(2, text);
|
assertSpanCount(2, text);
|
||||||
assertSpanEquals(styleSpan, text, 0);
|
assertSpanEquals(styleSpan, text, 0);
|
||||||
assertLocaleSpan(text, 1, 1, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 1, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if two jointed spans are merged into one span.
|
// Test if two jointed spans are merged into one span.
|
||||||
{
|
{
|
||||||
final SpannableString text = new SpannableString("0123456789");
|
final SpannableString text = new SpannableString("0123456789");
|
||||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 3,
|
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 3,
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 5, Locale.JAPANESE);
|
LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 5, Locale.JAPANESE);
|
||||||
assertSpanCount(1, text);
|
assertSpanCount(1, text);
|
||||||
assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if two overlapped spans are merged into one span.
|
// Test if two overlapped spans are merged into one span.
|
||||||
{
|
{
|
||||||
final SpannableString text = new SpannableString("0123456789");
|
final SpannableString text = new SpannableString("0123456789");
|
||||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 4,
|
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 4,
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 5, Locale.JAPANESE);
|
LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 5, Locale.JAPANESE);
|
||||||
assertSpanCount(1, text);
|
assertSpanCount(1, text);
|
||||||
assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if three overlapped spans are merged into one span.
|
// Test if three overlapped spans are merged into one span.
|
||||||
{
|
{
|
||||||
final SpannableString text = new SpannableString("0123456789");
|
final SpannableString text = new SpannableString("0123456789");
|
||||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 4,
|
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 4,
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 5, 6,
|
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 5, 6,
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 2, 8, Locale.JAPANESE);
|
LocaleSpanCompatUtils.updateLocaleSpan(text, 2, 8, Locale.JAPANESE);
|
||||||
assertSpanCount(1, text);
|
assertSpanCount(1, text);
|
||||||
assertLocaleSpan(text, 0, 1, 8, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 0, 1, 8, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if disjoint spans remain disjoint.
|
// Test if disjoint spans remain disjoint.
|
||||||
{
|
{
|
||||||
final SpannableString text = new SpannableString("0123456789");
|
final SpannableString text = new SpannableString("0123456789");
|
||||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 3,
|
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 3,
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 5, 6,
|
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 5, 6,
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 8, 9, Locale.JAPANESE);
|
LocaleSpanCompatUtils.updateLocaleSpan(text, 8, 9, Locale.JAPANESE);
|
||||||
assertSpanCount(3, text);
|
assertSpanCount(3, text);
|
||||||
assertLocaleSpan(text, 0, 1, 3, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 0, 1, 3, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
assertLocaleSpan(text, 1, 5, 6, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 1, 5, 6, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
assertLocaleSpan(text, 2, 8, 9, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 2, 8, 9, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if existing span flags are preserved during merge.
|
// Test if existing span flags are preserved during merge.
|
||||||
{
|
{
|
||||||
final SpannableString text = new SpannableString("0123456789");
|
final SpannableString text = new SpannableString("0123456789");
|
||||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 5,
|
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 5,
|
||||||
Spannable.SPAN_INCLUSIVE_INCLUSIVE | Spannable.SPAN_INTERMEDIATE);
|
Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE);
|
||||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 4, Locale.JAPANESE);
|
LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 4, Locale.JAPANESE);
|
||||||
assertSpanCount(1, text);
|
assertSpanCount(1, text);
|
||||||
assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE,
|
assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE,
|
||||||
Spannable.SPAN_INCLUSIVE_INCLUSIVE | Spannable.SPAN_INTERMEDIATE);
|
Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if existing span flags are preserved even when partially overlapped (leading edge).
|
// Test if existing span flags are preserved even when partially overlapped (leading edge).
|
||||||
{
|
{
|
||||||
final SpannableString text = new SpannableString("0123456789");
|
final SpannableString text = new SpannableString("0123456789");
|
||||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 5,
|
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 5,
|
||||||
Spannable.SPAN_INCLUSIVE_INCLUSIVE | Spannable.SPAN_INTERMEDIATE);
|
Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE);
|
||||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 7, Locale.JAPANESE);
|
LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 7, Locale.JAPANESE);
|
||||||
assertSpanCount(1, text);
|
assertSpanCount(1, text);
|
||||||
assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE,
|
assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE,
|
||||||
Spannable.SPAN_INCLUSIVE_EXCLUSIVE | Spannable.SPAN_INTERMEDIATE);
|
Spanned.SPAN_INCLUSIVE_EXCLUSIVE | Spanned.SPAN_INTERMEDIATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if existing span flags are preserved even when partially overlapped (trailing edge).
|
// Test if existing span flags are preserved even when partially overlapped (trailing edge).
|
||||||
{
|
{
|
||||||
final SpannableString text = new SpannableString("0123456789");
|
final SpannableString text = new SpannableString("0123456789");
|
||||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 3, 7,
|
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 3, 7,
|
||||||
Spannable.SPAN_INCLUSIVE_INCLUSIVE | Spannable.SPAN_INTERMEDIATE);
|
Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE);
|
||||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE);
|
LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE);
|
||||||
assertSpanCount(1, text);
|
assertSpanCount(1, text);
|
||||||
assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE,
|
assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE,
|
||||||
Spannable.SPAN_EXCLUSIVE_INCLUSIVE | Spannable.SPAN_INTERMEDIATE);
|
Spanned.SPAN_EXCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if existing locale span will be removed when the locale doesn't match.
|
// Test if existing locale span will be removed when the locale doesn't match.
|
||||||
{
|
{
|
||||||
final SpannableString text = new SpannableString("0123456789");
|
final SpannableString text = new SpannableString("0123456789");
|
||||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 5,
|
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 5,
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 7, Locale.JAPANESE);
|
LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 7, Locale.JAPANESE);
|
||||||
assertSpanCount(1, text);
|
assertSpanCount(1, text);
|
||||||
assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if existing locale span will be removed when the locale doesn't match. (case 2)
|
// Test if existing locale span will be removed when the locale doesn't match. (case 2)
|
||||||
{
|
{
|
||||||
final SpannableString text = new SpannableString("0123456789");
|
final SpannableString text = new SpannableString("0123456789");
|
||||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7,
|
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7,
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 5, 6, Locale.JAPANESE);
|
LocaleSpanCompatUtils.updateLocaleSpan(text, 5, 6, Locale.JAPANESE);
|
||||||
assertSpanCount(3, text);
|
assertSpanCount(3, text);
|
||||||
assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
assertLocaleSpan(text, 1, 6, 7, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 1, 6, 7, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
assertLocaleSpan(text, 2, 5, 6, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 2, 5, 6, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if existing locale span will be removed when the locale doesn't match. (case 3)
|
// Test if existing locale span will be removed when the locale doesn't match. (case 3)
|
||||||
{
|
{
|
||||||
final SpannableString text = new SpannableString("0123456789");
|
final SpannableString text = new SpannableString("0123456789");
|
||||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7,
|
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7,
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 2, 5, Locale.JAPANESE);
|
LocaleSpanCompatUtils.updateLocaleSpan(text, 2, 5, Locale.JAPANESE);
|
||||||
assertSpanCount(2, text);
|
assertSpanCount(2, text);
|
||||||
assertLocaleSpan(text, 0, 5, 7, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 0, 5, 7, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
assertLocaleSpan(text, 1, 2, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 1, 2, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if existing locale span will be removed when the locale doesn't match. (case 3)
|
// Test if existing locale span will be removed when the locale doesn't match. (case 3)
|
||||||
{
|
{
|
||||||
final SpannableString text = new SpannableString("0123456789");
|
final SpannableString text = new SpannableString("0123456789");
|
||||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7,
|
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7,
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 5, 8, Locale.JAPANESE);
|
LocaleSpanCompatUtils.updateLocaleSpan(text, 5, 8, Locale.JAPANESE);
|
||||||
assertSpanCount(2, text);
|
assertSpanCount(2, text);
|
||||||
assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
assertLocaleSpan(text, 1, 5, 8, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
assertLocaleSpan(text, 1, 5, 8, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,7 @@ public final class MoreKeySpecTests extends KeySpecParserTestsBase {
|
||||||
assertArrayEquals(message, expected, actual);
|
assertArrayEquals(message, expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("static-method")
|
||||||
public void testEmptyEntry() {
|
public void testEmptyEntry() {
|
||||||
assertInsertAdditionalMoreKeys("null more keys and null additons",
|
assertInsertAdditionalMoreKeys("null more keys and null additons",
|
||||||
null,
|
null,
|
||||||
|
@ -106,6 +107,7 @@ public final class MoreKeySpecTests extends KeySpecParserTestsBase {
|
||||||
new String[] { "a", "A", "b", "B", "c", "d" });
|
new String[] { "a", "A", "b", "B", "c", "d" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("static-method")
|
||||||
public void testInsertAdditionalMoreKeys() {
|
public void testInsertAdditionalMoreKeys() {
|
||||||
// Escaped marker.
|
// Escaped marker.
|
||||||
assertInsertAdditionalMoreKeys("escaped marker",
|
assertInsertAdditionalMoreKeys("escaped marker",
|
||||||
|
@ -306,6 +308,7 @@ public final class MoreKeySpecTests extends KeySpecParserTestsBase {
|
||||||
assertArrayEquals(message, expected, actual);
|
assertArrayEquals(message, expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("static-method")
|
||||||
public void testGetBooleanValue() {
|
public void testGetBooleanValue() {
|
||||||
assertGetBooleanValue("Has label", HAS_LABEL,
|
assertGetBooleanValue("Has label", HAS_LABEL,
|
||||||
new String[] { HAS_LABEL, "a", "b", "c" },
|
new String[] { HAS_LABEL, "a", "b", "c" },
|
||||||
|
@ -345,6 +348,7 @@ public final class MoreKeySpecTests extends KeySpecParserTestsBase {
|
||||||
assertArrayEquals(message, expected, actual);
|
assertArrayEquals(message, expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("static-method")
|
||||||
public void testGetIntValue() {
|
public void testGetIntValue() {
|
||||||
assertGetIntValue("Fixed column order 3", FIXED_COLUMN_ORDER, -1,
|
assertGetIntValue("Fixed column order 3", FIXED_COLUMN_ORDER, -1,
|
||||||
new String[] { FIXED_COLUMN_ORDER + "3", "a", "b", "c" },
|
new String[] { FIXED_COLUMN_ORDER + "3", "a", "b", "c" },
|
||||||
|
|
|
@ -174,13 +174,12 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
|
||||||
if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), formatVersion,
|
if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), formatVersion,
|
||||||
LocaleUtils.constructLocaleFromString(TEST_LOCALE), attributeMap)) {
|
LocaleUtils.constructLocaleFromString(TEST_LOCALE), attributeMap)) {
|
||||||
return file;
|
return file;
|
||||||
} else {
|
|
||||||
throw new IOException("Empty dictionary " + file.getAbsolutePath()
|
|
||||||
+ " cannot be created. Foramt version: " + formatVersion);
|
|
||||||
}
|
}
|
||||||
|
throw new IOException("Empty dictionary " + file.getAbsolutePath()
|
||||||
|
+ " cannot be created. Foramt version: " + formatVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BinaryDictionary getBinaryDictionary(final File dictFile) {
|
private static BinaryDictionary getBinaryDictionary(final File dictFile) {
|
||||||
return new BinaryDictionary(dictFile.getAbsolutePath(),
|
return new BinaryDictionary(dictFile.getAbsolutePath(),
|
||||||
0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
|
0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
|
||||||
Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
|
Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
|
||||||
|
@ -683,7 +682,7 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
|
||||||
final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
|
final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
|
||||||
|
|
||||||
binaryDictionary.addUnigramEntry("", DUMMY_PROBABILITY, "" /* shortcutTarget */,
|
binaryDictionary.addUnigramEntry("", DUMMY_PROBABILITY, "" /* shortcutTarget */,
|
||||||
BinaryDictionary.NOT_A_PROBABILITY /* shortcutProbability */,
|
Dictionary.NOT_A_PROBABILITY /* shortcutProbability */,
|
||||||
true /* isBeginningOfSentence */, true /* isNotAWord */,
|
true /* isBeginningOfSentence */, true /* isNotAWord */,
|
||||||
false /* isPossiblyOffensive */, mCurrentTime);
|
false /* isPossiblyOffensive */, mCurrentTime);
|
||||||
final NgramContext beginningOfSentenceContext = NgramContext.BEGINNING_OF_SENTENCE;
|
final NgramContext beginningOfSentenceContext = NgramContext.BEGINNING_OF_SENTENCE;
|
||||||
|
|
|
@ -111,13 +111,12 @@ public class BinaryDictionaryTests extends AndroidTestCase {
|
||||||
if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), formatVersion,
|
if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), formatVersion,
|
||||||
Locale.ENGLISH, attributeMap)) {
|
Locale.ENGLISH, attributeMap)) {
|
||||||
return file;
|
return file;
|
||||||
} else {
|
|
||||||
throw new IOException("Empty dictionary " + file.getAbsolutePath()
|
|
||||||
+ " cannot be created. Format version: " + formatVersion);
|
|
||||||
}
|
}
|
||||||
|
throw new IOException("Empty dictionary " + file.getAbsolutePath()
|
||||||
|
+ " cannot be created. Format version: " + formatVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BinaryDictionary getBinaryDictionary(final File dictFile) {
|
private static BinaryDictionary getBinaryDictionary(final File dictFile) {
|
||||||
return new BinaryDictionary(dictFile.getAbsolutePath(),
|
return new BinaryDictionary(dictFile.getAbsolutePath(),
|
||||||
0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
|
0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
|
||||||
Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
|
Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
|
||||||
|
@ -211,15 +210,14 @@ public class BinaryDictionaryTests extends AndroidTestCase {
|
||||||
|
|
||||||
assertEquals(probability, binaryDictionary.getFrequency("aaa"));
|
assertEquals(probability, binaryDictionary.getFrequency("aaa"));
|
||||||
assertEquals(updatedProbability, binaryDictionary.getFrequency(validLongWord));
|
assertEquals(updatedProbability, binaryDictionary.getFrequency(validLongWord));
|
||||||
assertEquals(BinaryDictionary.NOT_A_PROBABILITY,
|
assertEquals(Dictionary.NOT_A_PROBABILITY, binaryDictionary.getFrequency(invalidLongWord));
|
||||||
binaryDictionary.getFrequency(invalidLongWord));
|
|
||||||
assertEquals(updatedProbability, binaryDictionary.getFrequency("abc"));
|
assertEquals(updatedProbability, binaryDictionary.getFrequency("abc"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addUnigramWord(final BinaryDictionary binaryDictionary, final String word,
|
private static void addUnigramWord(final BinaryDictionary binaryDictionary, final String word,
|
||||||
final int probability) {
|
final int probability) {
|
||||||
binaryDictionary.addUnigramEntry(word, probability, "" /* shortcutTarget */,
|
binaryDictionary.addUnigramEntry(word, probability, "" /* shortcutTarget */,
|
||||||
BinaryDictionary.NOT_A_PROBABILITY /* shortcutProbability */,
|
Dictionary.NOT_A_PROBABILITY /* shortcutProbability */,
|
||||||
false /* isBeginningOfSentence */, false /* isNotAWord */,
|
false /* isBeginningOfSentence */, false /* isNotAWord */,
|
||||||
false /* isPossiblyOffensive */,
|
false /* isPossiblyOffensive */,
|
||||||
BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
|
BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
|
||||||
|
@ -975,7 +973,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
|
||||||
final boolean isPossiblyOffensive = random.nextBoolean();
|
final boolean isPossiblyOffensive = random.nextBoolean();
|
||||||
// TODO: Add tests for historical info.
|
// TODO: Add tests for historical info.
|
||||||
binaryDictionary.addUnigramEntry(word, unigramProbability,
|
binaryDictionary.addUnigramEntry(word, unigramProbability,
|
||||||
null /* shortcutTarget */, BinaryDictionary.NOT_A_PROBABILITY,
|
null /* shortcutTarget */, Dictionary.NOT_A_PROBABILITY,
|
||||||
false /* isBeginningOfSentence */, isNotAWord, isPossiblyOffensive,
|
false /* isBeginningOfSentence */, isNotAWord, isPossiblyOffensive,
|
||||||
BinaryDictionary.NOT_A_VALID_TIMESTAMP);
|
BinaryDictionary.NOT_A_VALID_TIMESTAMP);
|
||||||
if (binaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
|
if (binaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
|
||||||
|
@ -1264,7 +1262,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
|
||||||
WordProperty wordProperty = binaryDictionary.getWordProperty("ddd", false);
|
WordProperty wordProperty = binaryDictionary.getWordProperty("ddd", false);
|
||||||
assertEquals(true, wordProperty.mIsPossiblyOffensive);
|
assertEquals(true, wordProperty.mIsPossiblyOffensive);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDictMigration() {
|
public void testDictMigration() {
|
||||||
for (final int formatVersion : DICT_FORMAT_VERSIONS) {
|
for (final int formatVersion : DICT_FORMAT_VERSIONS) {
|
||||||
testDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, formatVersion);
|
testDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, formatVersion);
|
||||||
|
|
|
@ -61,7 +61,6 @@ public class BlueUnderlineTests extends InputTestsBase {
|
||||||
public void testBlueUnderlineOnBackspace() {
|
public void testBlueUnderlineOnBackspace() {
|
||||||
final String STRING_TO_TYPE = "tgis";
|
final String STRING_TO_TYPE = "tgis";
|
||||||
final int typedLength = STRING_TO_TYPE.length();
|
final int typedLength = STRING_TO_TYPE.length();
|
||||||
final int EXPECTED_SUGGESTION_SPAN_START = -1;
|
|
||||||
final int EXPECTED_UNDERLINE_SPAN_START = 0;
|
final int EXPECTED_UNDERLINE_SPAN_START = 0;
|
||||||
final int EXPECTED_UNDERLINE_SPAN_END = 3;
|
final int EXPECTED_UNDERLINE_SPAN_END = 3;
|
||||||
type(STRING_TO_TYPE);
|
type(STRING_TO_TYPE);
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class DictionaryFacilitatorLruCacheTests extends AndroidTestCase {
|
||||||
getContext(), MAX_CACHE_SIZE_LARGE, ""));
|
getContext(), MAX_CACHE_SIZE_LARGE, ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testGetFacilitator(final DictionaryFacilitatorLruCache cache) {
|
private static void testGetFacilitator(final DictionaryFacilitatorLruCache cache) {
|
||||||
final DictionaryFacilitator dictionaryFacilitatorEnUs = cache.get(Locale.US);
|
final DictionaryFacilitator dictionaryFacilitatorEnUs = cache.get(Locale.US);
|
||||||
assertNotNull(dictionaryFacilitatorEnUs);
|
assertNotNull(dictionaryFacilitatorEnUs);
|
||||||
assertTrue(dictionaryFacilitatorEnUs.isForLocales(new Locale[] { Locale.US }));
|
assertTrue(dictionaryFacilitatorEnUs.isForLocales(new Locale[] { Locale.US }));
|
||||||
|
@ -68,7 +68,7 @@ public class DictionaryFacilitatorLruCacheTests extends AndroidTestCase {
|
||||||
getContext(), MAX_CACHE_SIZE_LARGE, ""));
|
getContext(), MAX_CACHE_SIZE_LARGE, ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testSetUseContactsDictionary(final DictionaryFacilitatorLruCache cache) {
|
private static void testSetUseContactsDictionary(final DictionaryFacilitatorLruCache cache) {
|
||||||
assertNull(cache.get(Locale.US).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
|
assertNull(cache.get(Locale.US).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
|
||||||
cache.setUseContactsDictionary(true /* useContactsDictionary */);
|
cache.setUseContactsDictionary(true /* useContactsDictionary */);
|
||||||
assertNotNull(cache.get(Locale.US).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
|
assertNotNull(cache.get(Locale.US).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
|
||||||
|
|
|
@ -25,7 +25,7 @@ import java.util.ArrayList;
|
||||||
@LargeTest
|
@LargeTest
|
||||||
public class InputLogicTestsDeadKeys extends InputTestsBase {
|
public class InputLogicTestsDeadKeys extends InputTestsBase {
|
||||||
// A helper class for readability
|
// A helper class for readability
|
||||||
private static class EventList extends ArrayList<Event> {
|
static class EventList extends ArrayList<Event> {
|
||||||
public EventList addCodePoint(final int codePoint, final boolean isDead) {
|
public EventList addCodePoint(final int codePoint, final boolean isDead) {
|
||||||
final Event event;
|
final Event event;
|
||||||
if (isDead) {
|
if (isDead) {
|
||||||
|
|
|
@ -80,7 +80,6 @@ import android.util.Pair;
|
||||||
@LargeTest
|
@LargeTest
|
||||||
// These tests are inactive until the combining code for Myanmar Reordering is sorted out.
|
// These tests are inactive until the combining code for Myanmar Reordering is sorted out.
|
||||||
@Suppress
|
@Suppress
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public class InputLogicTestsReorderingMyanmar extends InputTestsBase {
|
public class InputLogicTestsReorderingMyanmar extends InputTestsBase {
|
||||||
// The tests are formatted as follows.
|
// The tests are formatted as follows.
|
||||||
// Each test is an entry in the array of Pair arrays.
|
// Each test is an entry in the array of Pair arrays.
|
||||||
|
@ -90,7 +89,7 @@ public class InputLogicTestsReorderingMyanmar extends InputTestsBase {
|
||||||
// member is stored the string that should be in the text view after this
|
// member is stored the string that should be in the text view after this
|
||||||
// key press.
|
// key press.
|
||||||
|
|
||||||
private static final Pair[][] TESTS = {
|
private static final Pair<?, ?>[][] TESTS = {
|
||||||
|
|
||||||
// Tests for U+1031 MYANMAR VOWEL SIGN E : ေ
|
// Tests for U+1031 MYANMAR VOWEL SIGN E : ေ
|
||||||
new Pair[] { // Type : U+1031 U+1000 U+101F ေ က ဟ
|
new Pair[] { // Type : U+1031 U+1000 U+101F ေ က ဟ
|
||||||
|
@ -206,13 +205,12 @@ public class InputLogicTestsReorderingMyanmar extends InputTestsBase {
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
private void doMyanmarTest(final int testNumber, final Pair<?, ?>[] test) {
|
||||||
private void doMyanmarTest(final int testNumber, final Pair[] test) {
|
|
||||||
int stepNumber = 0;
|
int stepNumber = 0;
|
||||||
for (final Pair<int[], String> step : test) {
|
for (final Pair<?, ?> step : test) {
|
||||||
++stepNumber;
|
++stepNumber;
|
||||||
final int[] input = step.first;
|
final int[] input = (int[]) step.first;
|
||||||
final String expectedResult = step.second;
|
final String expectedResult = (String) step.second;
|
||||||
if (input.length > 1) {
|
if (input.length > 1) {
|
||||||
mLatinIME.onTextInput(new String(input, 0, input.length));
|
mLatinIME.onTextInput(new String(input, 0, input.length));
|
||||||
} else {
|
} else {
|
||||||
|
@ -226,7 +224,7 @@ public class InputLogicTestsReorderingMyanmar extends InputTestsBase {
|
||||||
public void testMyanmarReordering() {
|
public void testMyanmarReordering() {
|
||||||
int testNumber = 0;
|
int testNumber = 0;
|
||||||
changeLanguage("my_MM", "CombiningRules=MyanmarReordering");
|
changeLanguage("my_MM", "CombiningRules=MyanmarReordering");
|
||||||
for (final Pair[] test : TESTS) {
|
for (final Pair<?, ?>[] test : TESTS) {
|
||||||
// Small trick to reset LatinIME : setText("") and send updateSelection with values
|
// Small trick to reset LatinIME : setText("") and send updateSelection with values
|
||||||
// LatinIME has never seen, and cursor pos 0,0.
|
// LatinIME has never seen, and cursor pos 0,0.
|
||||||
mEditText.setText("");
|
mEditText.setText("");
|
||||||
|
|
|
@ -40,7 +40,6 @@ import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
|
||||||
import com.android.inputmethod.event.Event;
|
import com.android.inputmethod.event.Event;
|
||||||
import com.android.inputmethod.keyboard.Key;
|
import com.android.inputmethod.keyboard.Key;
|
||||||
import com.android.inputmethod.keyboard.Keyboard;
|
import com.android.inputmethod.keyboard.Keyboard;
|
||||||
import com.android.inputmethod.latin.Dictionary;
|
|
||||||
import com.android.inputmethod.latin.Dictionary.PhonyDictionary;
|
import com.android.inputmethod.latin.Dictionary.PhonyDictionary;
|
||||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||||
import com.android.inputmethod.latin.settings.DebugSettings;
|
import com.android.inputmethod.latin.settings.DebugSettings;
|
||||||
|
@ -250,7 +249,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
|
||||||
// Now, Looper#loop() never exits in normal operation unless the Looper#quit() method
|
// Now, Looper#loop() never exits in normal operation unless the Looper#quit() method
|
||||||
// is called, which has a lot of bad side effects. We can however just throw an exception
|
// is called, which has a lot of bad side effects. We can however just throw an exception
|
||||||
// in the runnable which will unwind the stack and allow us to exit.
|
// in the runnable which will unwind the stack and allow us to exit.
|
||||||
private final class InterruptRunMessagesException extends RuntimeException {
|
final class InterruptRunMessagesException extends RuntimeException {
|
||||||
// Empty class
|
// Empty class
|
||||||
}
|
}
|
||||||
protected void runMessages() {
|
protected void runMessages() {
|
||||||
|
@ -284,7 +283,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
|
||||||
} else {
|
} else {
|
||||||
final int x = key.getX() + key.getWidth() / 2;
|
final int x = key.getX() + key.getWidth() / 2;
|
||||||
final int y = key.getY() + key.getHeight() / 2;
|
final int y = key.getY() + key.getHeight() / 2;
|
||||||
event = mLatinIME.createSoftwareKeypressEvent(codePoint, x, y, isKeyRepeat);
|
event = LatinIME.createSoftwareKeypressEvent(codePoint, x, y, isKeyRepeat);
|
||||||
}
|
}
|
||||||
mLatinIME.onEvent(event);
|
mLatinIME.onEvent(event);
|
||||||
// Also see the comment at the top of this function about onReleaseKey
|
// Also see the comment at the top of this function about onReleaseKey
|
||||||
|
@ -309,9 +308,8 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
|
||||||
final Key key = mKeyboard.getKey(codePoint);
|
final Key key = mKeyboard.getKey(codePoint);
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
throw new RuntimeException("Code point not on the keyboard");
|
throw new RuntimeException("Code point not on the keyboard");
|
||||||
} else {
|
|
||||||
return new Point(key.getX() + key.getWidth() / 2, key.getY() + key.getHeight() / 2);
|
|
||||||
}
|
}
|
||||||
|
return new Point(key.getX() + key.getWidth() / 2, key.getY() + key.getHeight() / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void gesture(final String stringToGesture) {
|
protected void gesture(final String stringToGesture) {
|
||||||
|
@ -386,7 +384,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
|
||||||
false /* isAuxiliary */,
|
false /* isAuxiliary */,
|
||||||
false /* overridesImplicitlyEnabledSubtype */,
|
false /* overridesImplicitlyEnabledSubtype */,
|
||||||
0 /* id */);
|
0 /* id */);
|
||||||
SubtypeSwitcher.getInstance().forceSubtype(subtype);
|
SubtypeSwitcher.forceSubtype(subtype);
|
||||||
mLatinIME.onCurrentInputMethodSubtypeChanged(subtype);
|
mLatinIME.onCurrentInputMethodSubtypeChanged(subtype);
|
||||||
runMessages();
|
runMessages();
|
||||||
mKeyboard = mLatinIME.mKeyboardSwitcher.getKeyboard();
|
mKeyboard = mLatinIME.mKeyboardSwitcher.getKeyboard();
|
||||||
|
|
|
@ -25,8 +25,8 @@ import android.test.suitebuilder.annotation.SmallTest;
|
||||||
public class NgramContextTests extends AndroidTestCase {
|
public class NgramContextTests extends AndroidTestCase {
|
||||||
public void testConstruct() {
|
public void testConstruct() {
|
||||||
assertEquals(new NgramContext(new WordInfo("a")), new NgramContext(new WordInfo("a")));
|
assertEquals(new NgramContext(new WordInfo("a")), new NgramContext(new WordInfo("a")));
|
||||||
assertEquals(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE),
|
assertEquals(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO),
|
||||||
new NgramContext(WordInfo.BEGINNING_OF_SENTENCE));
|
new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO));
|
||||||
assertEquals(new NgramContext(WordInfo.EMPTY_WORD_INFO),
|
assertEquals(new NgramContext(WordInfo.EMPTY_WORD_INFO),
|
||||||
new NgramContext(WordInfo.EMPTY_WORD_INFO));
|
new NgramContext(WordInfo.EMPTY_WORD_INFO));
|
||||||
assertEquals(new NgramContext(WordInfo.EMPTY_WORD_INFO),
|
assertEquals(new NgramContext(WordInfo.EMPTY_WORD_INFO),
|
||||||
|
@ -35,17 +35,18 @@ public class NgramContextTests extends AndroidTestCase {
|
||||||
|
|
||||||
public void testIsBeginningOfSentenceContext() {
|
public void testIsBeginningOfSentenceContext() {
|
||||||
assertFalse(new NgramContext().isBeginningOfSentenceContext());
|
assertFalse(new NgramContext().isBeginningOfSentenceContext());
|
||||||
assertTrue(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE)
|
assertTrue(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO)
|
||||||
.isBeginningOfSentenceContext());
|
.isBeginningOfSentenceContext());
|
||||||
assertTrue(NgramContext.BEGINNING_OF_SENTENCE.isBeginningOfSentenceContext());
|
assertTrue(NgramContext.BEGINNING_OF_SENTENCE.isBeginningOfSentenceContext());
|
||||||
assertFalse(new NgramContext(new WordInfo("a")).isBeginningOfSentenceContext());
|
assertFalse(new NgramContext(new WordInfo("a")).isBeginningOfSentenceContext());
|
||||||
assertFalse(new NgramContext(new WordInfo("")).isBeginningOfSentenceContext());
|
assertFalse(new NgramContext(new WordInfo("")).isBeginningOfSentenceContext());
|
||||||
assertFalse(new NgramContext(WordInfo.EMPTY_WORD_INFO).isBeginningOfSentenceContext());
|
assertFalse(new NgramContext(WordInfo.EMPTY_WORD_INFO).isBeginningOfSentenceContext());
|
||||||
assertTrue(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE, new WordInfo("a"))
|
assertTrue(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO, new WordInfo("a"))
|
||||||
.isBeginningOfSentenceContext());
|
.isBeginningOfSentenceContext());
|
||||||
assertFalse(new NgramContext(new WordInfo("a"), WordInfo.BEGINNING_OF_SENTENCE)
|
assertFalse(new NgramContext(new WordInfo("a"), WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO)
|
||||||
.isBeginningOfSentenceContext());
|
.isBeginningOfSentenceContext());
|
||||||
assertFalse(new NgramContext(WordInfo.EMPTY_WORD_INFO, WordInfo.BEGINNING_OF_SENTENCE)
|
assertFalse(new NgramContext(
|
||||||
|
WordInfo.EMPTY_WORD_INFO, WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO)
|
||||||
.isBeginningOfSentenceContext());
|
.isBeginningOfSentenceContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +57,7 @@ public class NgramContextTests extends AndroidTestCase {
|
||||||
assertEquals("b", ngramContext_b_a.getNthPrevWord(1));
|
assertEquals("b", ngramContext_b_a.getNthPrevWord(1));
|
||||||
assertEquals("a", ngramContext_b_a.getNthPrevWord(2));
|
assertEquals("a", ngramContext_b_a.getNthPrevWord(2));
|
||||||
final NgramContext ngramContext_bos_b =
|
final NgramContext ngramContext_bos_b =
|
||||||
ngramContext_b_a.getNextNgramContext(WordInfo.BEGINNING_OF_SENTENCE);
|
ngramContext_b_a.getNextNgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
|
||||||
assertTrue(ngramContext_bos_b.isBeginningOfSentenceContext());
|
assertTrue(ngramContext_bos_b.isBeginningOfSentenceContext());
|
||||||
assertEquals("b", ngramContext_bos_b.getNthPrevWord(2));
|
assertEquals("b", ngramContext_bos_b.getNthPrevWord(2));
|
||||||
final NgramContext ngramContext_c_bos =
|
final NgramContext ngramContext_c_bos =
|
||||||
|
|
|
@ -136,7 +136,7 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MockInputMethodService extends InputMethodService {
|
static class MockInputMethodService extends InputMethodService {
|
||||||
private MockConnection mMockConnection;
|
private MockConnection mMockConnection;
|
||||||
public void setInputConnection(final MockConnection mockConnection) {
|
public void setInputConnection(final MockConnection mockConnection) {
|
||||||
mMockConnection = mockConnection;
|
mMockConnection = mockConnection;
|
||||||
|
@ -221,7 +221,6 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
|
||||||
mSpacingAndPunctuations, new int[] { Constants.CODE_SPACE });
|
mSpacingAndPunctuations, new int[] { Constants.CODE_SPACE });
|
||||||
final SpacingAndPunctuations TAB = new SpacingAndPunctuations(
|
final SpacingAndPunctuations TAB = new SpacingAndPunctuations(
|
||||||
mSpacingAndPunctuations, new int[] { Constants.CODE_TAB });
|
mSpacingAndPunctuations, new int[] { Constants.CODE_TAB });
|
||||||
final int[] SPACE_TAB = StringUtils.toSortedCodePointArray(" \t");
|
|
||||||
// A character that needs surrogate pair to represent its code point (U+2008A).
|
// A character that needs surrogate pair to represent its code point (U+2008A).
|
||||||
final String SUPPLEMENTARY_CHAR_STRING = "\uD840\uDC8A";
|
final String SUPPLEMENTARY_CHAR_STRING = "\uD840\uDC8A";
|
||||||
final SpacingAndPunctuations SUPPLEMENTARY_CHAR = new SpacingAndPunctuations(
|
final SpacingAndPunctuations SUPPLEMENTARY_CHAR = new SpacingAndPunctuations(
|
||||||
|
|
|
@ -16,14 +16,10 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
import android.os.Build;
|
|
||||||
import android.test.suitebuilder.annotation.LargeTest;
|
import android.test.suitebuilder.annotation.LargeTest;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.Constants;
|
|
||||||
import com.android.inputmethod.latin.WordComposer;
|
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
public class ShiftModeTests extends InputTestsBase {
|
public class ShiftModeTests extends InputTestsBase {
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ public class SuggestedWordsTests extends AndroidTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for testGetTransformedWordInfo
|
// Helper for testGetTransformedWordInfo
|
||||||
private SuggestedWordInfo transformWordInfo(final String info,
|
private static SuggestedWordInfo transformWordInfo(final String info,
|
||||||
final int trailingSingleQuotesCount) {
|
final int trailingSingleQuotesCount) {
|
||||||
final SuggestedWordInfo suggestedWordInfo = createTypedWordInfo(info);
|
final SuggestedWordInfo suggestedWordInfo = createTypedWordInfo(info);
|
||||||
final SuggestedWordInfo returnedWordInfo =
|
final SuggestedWordInfo returnedWordInfo =
|
||||||
|
|
|
@ -117,7 +117,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
||||||
super.tearDown();
|
super.tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateWords(final int number, final Random random) {
|
private static void generateWords(final int number, final Random random) {
|
||||||
final int[] codePointSet = CodePointUtils.generateCodePointSet(DEFAULT_CODE_POINT_SET_SIZE,
|
final int[] codePointSet = CodePointUtils.generateCodePointSet(DEFAULT_CODE_POINT_SET_SIZE,
|
||||||
random);
|
random);
|
||||||
final Set<String> wordSet = new HashSet<>();
|
final Set<String> wordSet = new HashSet<>();
|
||||||
|
@ -138,7 +138,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
||||||
/**
|
/**
|
||||||
* Adds unigrams to the dictionary.
|
* Adds unigrams to the dictionary.
|
||||||
*/
|
*/
|
||||||
private void addUnigrams(final int number, final FusionDictionary dict,
|
private static void addUnigrams(final int number, final FusionDictionary dict,
|
||||||
final List<String> words, final HashMap<String, List<String>> shortcutMap) {
|
final List<String> words, final HashMap<String, List<String>> shortcutMap) {
|
||||||
for (int i = 0; i < number; ++i) {
|
for (int i = 0; i < number; ++i) {
|
||||||
final String word = words.get(i);
|
final String word = words.get(i);
|
||||||
|
@ -154,7 +154,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addBigrams(final FusionDictionary dict,
|
private static void addBigrams(final FusionDictionary dict,
|
||||||
final List<String> words,
|
final List<String> words,
|
||||||
final SparseArray<List<Integer>> bigrams) {
|
final SparseArray<List<Integer>> bigrams) {
|
||||||
for (int i = 0; i < bigrams.size(); ++i) {
|
for (int i = 0; i < bigrams.size(); ++i) {
|
||||||
|
@ -173,7 +173,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
||||||
// new java.io.FileWriter(new File(filename)), dict);
|
// new java.io.FileWriter(new File(filename)), dict);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
private long timeWritingDictToFile(final File file, final FusionDictionary dict,
|
private static long timeWritingDictToFile(final File file, final FusionDictionary dict,
|
||||||
final FormatSpec.FormatOptions formatOptions) {
|
final FormatSpec.FormatOptions formatOptions) {
|
||||||
|
|
||||||
long now = -1, diff = -1;
|
long now = -1, diff = -1;
|
||||||
|
@ -196,7 +196,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkDictionary(final FusionDictionary dict, final List<String> words,
|
private static void checkDictionary(final FusionDictionary dict, final List<String> words,
|
||||||
final SparseArray<List<Integer>> bigrams,
|
final SparseArray<List<Integer>> bigrams,
|
||||||
final HashMap<String, List<String>> shortcutMap) {
|
final HashMap<String, List<String>> shortcutMap) {
|
||||||
assertNotNull(dict);
|
assertNotNull(dict);
|
||||||
|
@ -231,16 +231,16 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String outputOptions(final int bufferType,
|
private static String outputOptions(final int bufferType,
|
||||||
final FormatSpec.FormatOptions formatOptions) {
|
final FormatSpec.FormatOptions formatOptions) {
|
||||||
String result = " : buffer type = "
|
final String result = " : buffer type = "
|
||||||
+ ((bufferType == BinaryDictUtils.USE_BYTE_BUFFER) ? "byte buffer" : "byte array");
|
+ ((bufferType == BinaryDictUtils.USE_BYTE_BUFFER) ? "byte buffer" : "byte array");
|
||||||
return result + " : version = " + formatOptions.mVersion;
|
return result + " : version = " + formatOptions.mVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests for readDictionaryBinary and writeDictionaryBinary
|
// Tests for readDictionaryBinary and writeDictionaryBinary
|
||||||
|
|
||||||
private long timeReadingAndCheckDict(final File file, final List<String> words,
|
private static long timeReadingAndCheckDict(final File file, final List<String> words,
|
||||||
final SparseArray<List<Integer>> bigrams,
|
final SparseArray<List<Integer>> bigrams,
|
||||||
final HashMap<String, List<String>> shortcutMap, final int bufferType) {
|
final HashMap<String, List<String>> shortcutMap, final int bufferType) {
|
||||||
long now, diff = -1;
|
long now, diff = -1;
|
||||||
|
@ -385,7 +385,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
||||||
|
|
||||||
// Tests for readUnigramsAndBigramsBinary
|
// Tests for readUnigramsAndBigramsBinary
|
||||||
|
|
||||||
private void checkWordMap(final List<String> expectedWords,
|
private static void checkWordMap(final List<String> expectedWords,
|
||||||
final SparseArray<List<Integer>> expectedBigrams,
|
final SparseArray<List<Integer>> expectedBigrams,
|
||||||
final TreeMap<Integer, String> resultWords,
|
final TreeMap<Integer, String> resultWords,
|
||||||
final TreeMap<Integer, Integer> resultFrequencies,
|
final TreeMap<Integer, Integer> resultFrequencies,
|
||||||
|
@ -434,9 +434,9 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
||||||
assertEquals(actBigrams, expBigrams);
|
assertEquals(actBigrams, expBigrams);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long timeAndCheckReadUnigramsAndBigramsBinary(final File file, final List<String> words,
|
private static long timeAndCheckReadUnigramsAndBigramsBinary(final File file,
|
||||||
final SparseArray<List<Integer>> bigrams, final int bufferType,
|
final List<String> words, final SparseArray<List<Integer>> bigrams,
|
||||||
final boolean checkProbability) {
|
final int bufferType, final boolean checkProbability) {
|
||||||
final TreeMap<Integer, String> resultWords = new TreeMap<>();
|
final TreeMap<Integer, String> resultWords = new TreeMap<>();
|
||||||
final TreeMap<Integer, ArrayList<PendingAttribute>> resultBigrams = new TreeMap<>();
|
final TreeMap<Integer, ArrayList<PendingAttribute>> resultBigrams = new TreeMap<>();
|
||||||
final TreeMap<Integer, Integer> resultFreqs = new TreeMap<>();
|
final TreeMap<Integer, Integer> resultFreqs = new TreeMap<>();
|
||||||
|
@ -519,7 +519,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests for getTerminalPosition
|
// Tests for getTerminalPosition
|
||||||
private String getWordFromBinary(final DictDecoder dictDecoder, final int address) {
|
private static String getWordFromBinary(final DictDecoder dictDecoder, final int address) {
|
||||||
if (dictDecoder.getPosition() != 0) dictDecoder.setPosition(0);
|
if (dictDecoder.getPosition() != 0) dictDecoder.setPosition(0);
|
||||||
|
|
||||||
DictionaryHeader fileHeader = null;
|
DictionaryHeader fileHeader = null;
|
||||||
|
@ -535,7 +535,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
||||||
address).mWord;
|
address).mWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long checkGetTerminalPosition(final DictDecoder dictDecoder, final String word,
|
private static long checkGetTerminalPosition(final DictDecoder dictDecoder, final String word,
|
||||||
final boolean contained) {
|
final boolean contained) {
|
||||||
long diff = -1;
|
long diff = -1;
|
||||||
int position = -1;
|
int position = -1;
|
||||||
|
|
|
@ -113,15 +113,16 @@ public final class BinaryDictDecoderUtils {
|
||||||
/**
|
/**
|
||||||
* Helper method to find out whether this code fits on one byte
|
* Helper method to find out whether this code fits on one byte
|
||||||
*/
|
*/
|
||||||
private static boolean fitsOnOneByte(int character,
|
private static boolean fitsOnOneByte(final int character,
|
||||||
final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
|
final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
|
||||||
|
int codePoint = character;
|
||||||
if (codePointToOneByteCodeMap != null) {
|
if (codePointToOneByteCodeMap != null) {
|
||||||
if (codePointToOneByteCodeMap.containsKey(character)) {
|
if (codePointToOneByteCodeMap.containsKey(character)) {
|
||||||
character = codePointToOneByteCodeMap.get(character);
|
codePoint = codePointToOneByteCodeMap.get(character);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return character >= FormatSpec.MINIMAL_ONE_BYTE_CHARACTER_VALUE
|
return codePoint >= FormatSpec.MINIMAL_ONE_BYTE_CHARACTER_VALUE
|
||||||
&& character <= FormatSpec.MAXIMAL_ONE_BYTE_CHARACTER_VALUE;
|
&& codePoint <= FormatSpec.MAXIMAL_ONE_BYTE_CHARACTER_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -168,8 +169,9 @@ public final class BinaryDictDecoderUtils {
|
||||||
* @param codePointToOneByteCodeMap the map to convert the code point.
|
* @param codePointToOneByteCodeMap the map to convert the code point.
|
||||||
* @return the index after the last character.
|
* @return the index after the last character.
|
||||||
*/
|
*/
|
||||||
static int writeCharArray(final int[] codePoints, final byte[] buffer, int index,
|
static int writeCharArray(final int[] codePoints, final byte[] buffer, final int fromIndex,
|
||||||
final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
|
final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
|
||||||
|
int index = fromIndex;
|
||||||
for (int codePoint : codePoints) {
|
for (int codePoint : codePoints) {
|
||||||
if (codePointToOneByteCodeMap != null) {
|
if (codePointToOneByteCodeMap != null) {
|
||||||
if (codePointToOneByteCodeMap.containsKey(codePoint)) {
|
if (codePointToOneByteCodeMap.containsKey(codePoint)) {
|
||||||
|
@ -293,10 +295,9 @@ public final class BinaryDictDecoderUtils {
|
||||||
final int msb = dictBuffer.readUnsignedByte();
|
final int msb = dictBuffer.readUnsignedByte();
|
||||||
if (FormatSpec.MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT >= msb) {
|
if (FormatSpec.MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT >= msb) {
|
||||||
return msb;
|
return msb;
|
||||||
} else {
|
|
||||||
return ((FormatSpec.MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT & msb) << 8)
|
|
||||||
+ dictBuffer.readUnsignedByte();
|
|
||||||
}
|
}
|
||||||
|
return ((FormatSpec.MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT & msb) << 8)
|
||||||
|
+ dictBuffer.readUnsignedByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -199,8 +199,9 @@ public class BinaryDictEncoderUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int writeUIntToBuffer(final byte[] buffer, int position, final int value,
|
static int writeUIntToBuffer(final byte[] buffer, final int fromPosition, final int value,
|
||||||
final int size) {
|
final int size) {
|
||||||
|
int position = fromPosition;
|
||||||
switch(size) {
|
switch(size) {
|
||||||
case 4:
|
case 4:
|
||||||
buffer[position++] = (byte) ((value >> 24) & 0xFF);
|
buffer[position++] = (byte) ((value >> 24) & 0xFF);
|
||||||
|
@ -324,11 +325,9 @@ public class BinaryDictEncoderUtils {
|
||||||
return targetNodeArray.mCachedAddressAfterUpdate
|
return targetNodeArray.mCachedAddressAfterUpdate
|
||||||
- (currentNodeArray.mCachedAddressAfterUpdate
|
- (currentNodeArray.mCachedAddressAfterUpdate
|
||||||
+ offsetFromStartOfCurrentNodeArray);
|
+ offsetFromStartOfCurrentNodeArray);
|
||||||
} else {
|
|
||||||
return targetNodeArray.mCachedAddressBeforeUpdate
|
|
||||||
- (currentNodeArray.mCachedAddressBeforeUpdate
|
|
||||||
+ offsetFromStartOfCurrentNodeArray);
|
|
||||||
}
|
}
|
||||||
|
return targetNodeArray.mCachedAddressBeforeUpdate
|
||||||
|
- (currentNodeArray.mCachedAddressBeforeUpdate + offsetFromStartOfCurrentNodeArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -356,9 +355,8 @@ public class BinaryDictEncoderUtils {
|
||||||
final int newOffsetBasePoint = currentNodeArray.mCachedAddressAfterUpdate
|
final int newOffsetBasePoint = currentNodeArray.mCachedAddressAfterUpdate
|
||||||
+ offsetFromStartOfCurrentNodeArray;
|
+ offsetFromStartOfCurrentNodeArray;
|
||||||
return targetPtNode.mCachedAddressAfterUpdate - newOffsetBasePoint;
|
return targetPtNode.mCachedAddressAfterUpdate - newOffsetBasePoint;
|
||||||
} else {
|
|
||||||
return targetPtNode.mCachedAddressBeforeUpdate - oldOffsetBasePoint;
|
|
||||||
}
|
}
|
||||||
|
return targetPtNode.mCachedAddressBeforeUpdate - oldOffsetBasePoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -541,8 +539,9 @@ public class BinaryDictEncoderUtils {
|
||||||
* @param position the position to write.
|
* @param position the position to write.
|
||||||
* @return the size in bytes the address actually took.
|
* @return the size in bytes the address actually took.
|
||||||
*/
|
*/
|
||||||
/* package */ static int writeChildrenPosition(final byte[] buffer, int index,
|
/* package */ static int writeChildrenPosition(final byte[] buffer, final int fromIndex,
|
||||||
final int position) {
|
final int position) {
|
||||||
|
int index = fromIndex;
|
||||||
switch (getByteSize(position)) {
|
switch (getByteSize(position)) {
|
||||||
case 1:
|
case 1:
|
||||||
buffer[index++] = (byte)position;
|
buffer[index++] = (byte)position;
|
||||||
|
@ -623,7 +622,7 @@ public class BinaryDictEncoderUtils {
|
||||||
* @return the flags
|
* @return the flags
|
||||||
*/
|
*/
|
||||||
/* package */ static final int makeBigramFlags(final boolean more, final int offset,
|
/* package */ static final int makeBigramFlags(final boolean more, final int offset,
|
||||||
int bigramFrequency, final int unigramFrequency, final String word) {
|
final int bigramFrequency, final int unigramFrequency, final String word) {
|
||||||
int bigramFlags = (more ? FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT : 0)
|
int bigramFlags = (more ? FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT : 0)
|
||||||
+ (offset < 0 ? FormatSpec.FLAG_BIGRAM_ATTR_OFFSET_NEGATIVE : 0);
|
+ (offset < 0 ? FormatSpec.FLAG_BIGRAM_ATTR_OFFSET_NEGATIVE : 0);
|
||||||
switch (getByteSize(offset)) {
|
switch (getByteSize(offset)) {
|
||||||
|
@ -639,13 +638,16 @@ public class BinaryDictEncoderUtils {
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("Strange offset size");
|
throw new RuntimeException("Strange offset size");
|
||||||
}
|
}
|
||||||
|
final int frequency;
|
||||||
if (unigramFrequency > bigramFrequency) {
|
if (unigramFrequency > bigramFrequency) {
|
||||||
MakedictLog.e("Unigram freq is superior to bigram freq for \"" + word
|
MakedictLog.e("Unigram freq is superior to bigram freq for \"" + word
|
||||||
+ "\". Bigram freq is " + bigramFrequency + ", unigram freq for "
|
+ "\". Bigram freq is " + bigramFrequency + ", unigram freq for "
|
||||||
+ word + " is " + unigramFrequency);
|
+ word + " is " + unigramFrequency);
|
||||||
bigramFrequency = unigramFrequency;
|
frequency = unigramFrequency;
|
||||||
|
} else {
|
||||||
|
frequency = bigramFrequency;
|
||||||
}
|
}
|
||||||
bigramFlags += getBigramFrequencyDiff(unigramFrequency, bigramFrequency)
|
bigramFlags += getBigramFrequencyDiff(unigramFrequency, frequency)
|
||||||
& FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY;
|
& FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY;
|
||||||
return bigramFlags;
|
return bigramFlags;
|
||||||
}
|
}
|
||||||
|
@ -722,7 +724,6 @@ public class BinaryDictEncoderUtils {
|
||||||
* @param ptNodeArray the node array to write.
|
* @param ptNodeArray the node array to write.
|
||||||
* @param codePointToOneByteCodeMap the map to convert the code points.
|
* @param codePointToOneByteCodeMap the map to convert the code points.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
|
||||||
/* package */ static void writePlacedPtNodeArray(final FusionDictionary dict,
|
/* package */ static void writePlacedPtNodeArray(final FusionDictionary dict,
|
||||||
final DictEncoder dictEncoder, final PtNodeArray ptNodeArray,
|
final DictEncoder dictEncoder, final PtNodeArray ptNodeArray,
|
||||||
final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
|
final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
|
||||||
|
|
|
@ -206,11 +206,7 @@ public final class BinaryDictIOUtils {
|
||||||
if (same) {
|
if (same) {
|
||||||
// found the PtNode matches the word.
|
// found the PtNode matches the word.
|
||||||
if (wordPos + currentInfo.mCharacters.length == wordLen) {
|
if (wordPos + currentInfo.mCharacters.length == wordLen) {
|
||||||
if (!currentInfo.isTerminal()) {
|
return currentInfo.isTerminal() ? ptNodePos : FormatSpec.NOT_VALID_WORD;
|
||||||
return FormatSpec.NOT_VALID_WORD;
|
|
||||||
} else {
|
|
||||||
return ptNodePos;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
wordPos += currentInfo.mCharacters.length;
|
wordPos += currentInfo.mCharacters.length;
|
||||||
if (currentInfo.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS) {
|
if (currentInfo.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS) {
|
||||||
|
|
|
@ -142,11 +142,7 @@ public final class FusionDictionary implements Iterable<WordProperty> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getProbability() {
|
public int getProbability() {
|
||||||
if (isTerminal()) {
|
return isTerminal() ? mProbabilityInfo.mProbability : NOT_A_TERMINAL;
|
||||||
return mProbabilityInfo.mProbability;
|
|
||||||
} else {
|
|
||||||
return NOT_A_TERMINAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getIsNotAWord() {
|
public boolean getIsNotAWord() {
|
||||||
|
@ -235,7 +231,7 @@ public final class FusionDictionary implements Iterable<WordProperty> {
|
||||||
* the existing ones if any. Note: unigram, bigram, and shortcut frequencies are only
|
* the existing ones if any. Note: unigram, bigram, and shortcut frequencies are only
|
||||||
* updated if they are higher than the existing ones.
|
* updated if they are higher than the existing ones.
|
||||||
*/
|
*/
|
||||||
private void update(final ProbabilityInfo probabilityInfo,
|
void update(final ProbabilityInfo probabilityInfo,
|
||||||
final ArrayList<WeightedString> shortcutTargets,
|
final ArrayList<WeightedString> shortcutTargets,
|
||||||
final ArrayList<WeightedString> bigrams,
|
final ArrayList<WeightedString> bigrams,
|
||||||
final boolean isNotAWord, final boolean isPossiblyOffensive) {
|
final boolean isNotAWord, final boolean isPossiblyOffensive) {
|
||||||
|
@ -337,15 +333,15 @@ public final class FusionDictionary implements Iterable<WordProperty> {
|
||||||
* This method checks that all PtNodes in a node array are ordered as expected.
|
* This method checks that all PtNodes in a node array are ordered as expected.
|
||||||
* If they are, nothing happens. If they aren't, an exception is thrown.
|
* If they are, nothing happens. If they aren't, an exception is thrown.
|
||||||
*/
|
*/
|
||||||
private void checkStack(PtNodeArray ptNodeArray) {
|
private static void checkStack(PtNodeArray ptNodeArray) {
|
||||||
ArrayList<PtNode> stack = ptNodeArray.mData;
|
ArrayList<PtNode> stack = ptNodeArray.mData;
|
||||||
int lastValue = -1;
|
int lastValue = -1;
|
||||||
for (int i = 0; i < stack.size(); ++i) {
|
for (int i = 0; i < stack.size(); ++i) {
|
||||||
int currentValue = stack.get(i).mChars[0];
|
int currentValue = stack.get(i).mChars[0];
|
||||||
if (currentValue <= lastValue)
|
if (currentValue <= lastValue) {
|
||||||
throw new RuntimeException("Invalid stack");
|
throw new RuntimeException("Invalid stack");
|
||||||
else
|
}
|
||||||
lastValue = currentValue;
|
lastValue = currentValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,14 +517,14 @@ public final class FusionDictionary implements Iterable<WordProperty> {
|
||||||
* is ignored.
|
* is ignored.
|
||||||
* This comparator imposes orderings that are inconsistent with equals.
|
* This comparator imposes orderings that are inconsistent with equals.
|
||||||
*/
|
*/
|
||||||
static private final class PtNodeComparator implements java.util.Comparator<PtNode> {
|
static final class PtNodeComparator implements java.util.Comparator<PtNode> {
|
||||||
@Override
|
@Override
|
||||||
public int compare(PtNode p1, PtNode p2) {
|
public int compare(PtNode p1, PtNode p2) {
|
||||||
if (p1.mChars[0] == p2.mChars[0]) return 0;
|
if (p1.mChars[0] == p2.mChars[0]) return 0;
|
||||||
return p1.mChars[0] < p2.mChars[0] ? -1 : 1;
|
return p1.mChars[0] < p2.mChars[0] ? -1 : 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final static private PtNodeComparator PTNODE_COMPARATOR = new PtNodeComparator();
|
final static PtNodeComparator PTNODE_COMPARATOR = new PtNodeComparator();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the insertion index of a character within a node array.
|
* Finds the insertion index of a character within a node array.
|
||||||
|
@ -559,7 +555,8 @@ public final class FusionDictionary implements Iterable<WordProperty> {
|
||||||
/**
|
/**
|
||||||
* Helper method to find a word in a given branch.
|
* Helper method to find a word in a given branch.
|
||||||
*/
|
*/
|
||||||
public static PtNode findWordInTree(PtNodeArray nodeArray, final String string) {
|
public static PtNode findWordInTree(final PtNodeArray rootNodeArray, final String string) {
|
||||||
|
PtNodeArray nodeArray = rootNodeArray;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
final StringBuilder checker = DBG ? new StringBuilder() : null;
|
final StringBuilder checker = DBG ? new StringBuilder() : null;
|
||||||
final int[] codePoints = getCodePoints(string);
|
final int[] codePoints = getCodePoints(string);
|
||||||
|
|
|
@ -36,17 +36,17 @@ public class Ver2DictDecoder extends AbstractDictDecoder {
|
||||||
/**
|
/**
|
||||||
* A utility class for reading a PtNode.
|
* A utility class for reading a PtNode.
|
||||||
*/
|
*/
|
||||||
protected static class PtNodeReader {
|
static class PtNodeReader {
|
||||||
private static ProbabilityInfo readProbabilityInfo(final DictBuffer dictBuffer) {
|
static ProbabilityInfo readProbabilityInfo(final DictBuffer dictBuffer) {
|
||||||
// Ver2 dicts don't contain historical information.
|
// Ver2 dicts don't contain historical information.
|
||||||
return new ProbabilityInfo(dictBuffer.readUnsignedByte());
|
return new ProbabilityInfo(dictBuffer.readUnsignedByte());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static int readPtNodeOptionFlags(final DictBuffer dictBuffer) {
|
static int readPtNodeOptionFlags(final DictBuffer dictBuffer) {
|
||||||
return dictBuffer.readUnsignedByte();
|
return dictBuffer.readUnsignedByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static int readChildrenAddress(final DictBuffer dictBuffer,
|
static int readChildrenAddress(final DictBuffer dictBuffer,
|
||||||
final int ptNodeFlags) {
|
final int ptNodeFlags) {
|
||||||
switch (ptNodeFlags & FormatSpec.MASK_CHILDREN_ADDRESS_TYPE) {
|
switch (ptNodeFlags & FormatSpec.MASK_CHILDREN_ADDRESS_TYPE) {
|
||||||
case FormatSpec.FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE:
|
case FormatSpec.FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE:
|
||||||
|
@ -62,7 +62,7 @@ public class Ver2DictDecoder extends AbstractDictDecoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reads shortcuts and returns the read length.
|
// Reads shortcuts and returns the read length.
|
||||||
protected static int readShortcut(final DictBuffer dictBuffer,
|
static int readShortcut(final DictBuffer dictBuffer,
|
||||||
final ArrayList<WeightedString> shortcutTargets) {
|
final ArrayList<WeightedString> shortcutTargets) {
|
||||||
final int pointerBefore = dictBuffer.position();
|
final int pointerBefore = dictBuffer.position();
|
||||||
dictBuffer.readUnsignedShort(); // skip the size
|
dictBuffer.readUnsignedShort(); // skip the size
|
||||||
|
@ -76,7 +76,7 @@ public class Ver2DictDecoder extends AbstractDictDecoder {
|
||||||
return dictBuffer.position() - pointerBefore;
|
return dictBuffer.position() - pointerBefore;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static int readBigramAddresses(final DictBuffer dictBuffer,
|
static int readBigramAddresses(final DictBuffer dictBuffer,
|
||||||
final ArrayList<PendingAttribute> bigrams, final int baseAddress) {
|
final ArrayList<PendingAttribute> bigrams, final int baseAddress) {
|
||||||
int readLength = 0;
|
int readLength = 0;
|
||||||
int bigramCount = 0;
|
int bigramCount = 0;
|
||||||
|
|
|
@ -27,14 +27,12 @@ import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
|
||||||
|
|
||||||
import android.test.AndroidTestCase;
|
import android.test.AndroidTestCase;
|
||||||
import android.test.suitebuilder.annotation.LargeTest;
|
import android.test.suitebuilder.annotation.LargeTest;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for Ver2DictEncoder
|
* Unit tests for Ver2DictEncoder
|
||||||
*/
|
*/
|
||||||
@LargeTest
|
@LargeTest
|
||||||
public class Ver2DictEncoderTests extends AndroidTestCase {
|
public class Ver2DictEncoderTests extends AndroidTestCase {
|
||||||
private static final String TAG = Ver2DictEncoderTests.class.getSimpleName();
|
|
||||||
private static final int UNIGRAM_FREQ = 10;
|
private static final int UNIGRAM_FREQ = 10;
|
||||||
|
|
||||||
public void testCodePointTable() {
|
public void testCodePointTable() {
|
||||||
|
@ -75,7 +73,7 @@ public class Ver2DictEncoderTests extends AndroidTestCase {
|
||||||
/**
|
/**
|
||||||
* Adds unigrams to the dictionary.
|
* Adds unigrams to the dictionary.
|
||||||
*/
|
*/
|
||||||
private void addUnigrams(final FusionDictionary dict, final List<String> words,
|
private static void addUnigrams(final FusionDictionary dict, final List<String> words,
|
||||||
final HashMap<String, List<String>> shortcutMap) {
|
final HashMap<String, List<String>> shortcutMap) {
|
||||||
for (final String word : words) {
|
for (final String word : words) {
|
||||||
final ArrayList<WeightedString> shortcuts = new ArrayList<>();
|
final ArrayList<WeightedString> shortcuts = new ArrayList<>();
|
||||||
|
|
|
@ -128,7 +128,7 @@ public class BlockingHttpClientTests extends AndroidTestCase {
|
||||||
assertTrue("ResponseProcessor was not invoked", processor.mInvoked);
|
assertTrue("ResponseProcessor was not invoked", processor.mInvoked);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class FakeErrorResponseProcessor implements ResponseProcessor<Void> {
|
static class FakeErrorResponseProcessor implements ResponseProcessor<Void> {
|
||||||
@Override
|
@Override
|
||||||
public Void onSuccess(InputStream response) {
|
public Void onSuccess(InputStream response) {
|
||||||
fail("Expected an error but received success");
|
fail("Expected an error but received success");
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue