Merge "Fix some compiler warnings"
This commit is contained in:
commit
46a007261f
115 changed files with 913 additions and 920 deletions
|
@ -346,7 +346,8 @@ final class KeyCodeDescriptionMapper {
|
|||
}
|
||||
|
||||
// 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 int textLength = outputText.length();
|
||||
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())) {
|
||||
return mAccessibilityUtils.getAutoCorrectionDescription(
|
||||
keyCodeDescription, shouldObscure);
|
||||
} else {
|
||||
return keyCodeDescription;
|
||||
}
|
||||
return keyCodeDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -144,7 +144,7 @@ public final class CompatUtils {
|
|||
|
||||
public <T> ToObjectMethodWrapper<T> getMethod(final String name,
|
||||
final T defaultValue, final Class<?>... parameterTypes) {
|
||||
return new ToObjectMethodWrapper<T>(CompatUtils.getMethod(mClass, name, parameterTypes),
|
||||
return new ToObjectMethodWrapper<>(CompatUtils.getMethod(mClass, name, parameterTypes),
|
||||
defaultValue);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ public class CursorAnchorInfoCompatWrapper {
|
|||
*/
|
||||
public static final int FLAG_IS_RTL = 0x04;
|
||||
|
||||
private CursorAnchorInfoCompatWrapper() {
|
||||
CursorAnchorInfoCompatWrapper() {
|
||||
// This class is not publicly instantiable.
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.android.inputmethod.compat;
|
||||
|
||||
import android.text.Spannable;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.LocaleSpan;
|
||||
import android.util.Log;
|
||||
|
||||
|
@ -127,13 +128,13 @@ public final class LocaleSpanCompatUtils {
|
|||
final int spanFlag = spannable.getSpanFlags(existingLocaleSpan);
|
||||
if (spanStart < newStart) {
|
||||
newStart = spanStart;
|
||||
isStartExclusive = ((spanFlag & Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) ==
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
isStartExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
if (newEnd < spanEnd) {
|
||||
newEnd = spanEnd;
|
||||
isEndExclusive = ((spanFlag & Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) ==
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
isEndExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
existingLocaleSpansToBeMerged.add(existingLocaleSpan);
|
||||
}
|
||||
|
@ -201,24 +202,17 @@ public final class LocaleSpanCompatUtils {
|
|||
|
||||
private static int getSpanFlag(final int originalFlag,
|
||||
final boolean isStartExclusive, final boolean isEndExclusive) {
|
||||
return (originalFlag & ~Spannable.SPAN_POINT_MARK_MASK) |
|
||||
return (originalFlag & ~Spanned.SPAN_POINT_MARK_MASK) |
|
||||
getSpanPointMarkFlag(isStartExclusive, isEndExclusive);
|
||||
}
|
||||
|
||||
private static int getSpanPointMarkFlag(final boolean isStartExclusive,
|
||||
final boolean isEndExclusive) {
|
||||
if (isStartExclusive) {
|
||||
if (isEndExclusive) {
|
||||
return Spannable.SPAN_EXCLUSIVE_EXCLUSIVE;
|
||||
} else {
|
||||
return Spannable.SPAN_EXCLUSIVE_INCLUSIVE;
|
||||
}
|
||||
} else {
|
||||
if (isEndExclusive) {
|
||||
return Spannable.SPAN_INCLUSIVE_EXCLUSIVE;
|
||||
} else {
|
||||
return Spannable.SPAN_INCLUSIVE_INCLUSIVE;
|
||||
}
|
||||
return isEndExclusive ? Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
: Spanned.SPAN_EXCLUSIVE_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);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static Notification build(final Notification.Builder builder) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
// #build was added in API level 16, JELLY_BEAN
|
||||
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);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
final View oldButton = getButton(oldStatus);
|
||||
final View newButton = getButton(newStatus);
|
||||
if (null != oldButton && null != newButton) {
|
||||
// Transition between two buttons : animate out, then in
|
||||
animateButton(oldButton, ANIMATION_OUT).setListener(
|
||||
new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(final Animator animation) {
|
||||
if (newStatus != mStatus) return;
|
||||
animateButton(newButton, ANIMATION_IN);
|
||||
}
|
||||
});
|
||||
animateButton(oldButton, ANIMATION_OUT).setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(final Animator animation) {
|
||||
animateButtonIfStatusIsEqual(newButton, newStatus);
|
||||
}
|
||||
});
|
||||
} else if (null != oldButton) {
|
||||
animateButton(oldButton, ANIMATION_OUT);
|
||||
} else if (null != newButton) {
|
||||
|
@ -159,9 +163,8 @@ public class ButtonSwitcher extends FrameLayout {
|
|||
if (ANIMATION_IN == direction) {
|
||||
button.setClickable(true);
|
||||
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;
|
||||
@Override
|
||||
public void run() {
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.util.HashMap;
|
|||
* in case some dictionaries appeared, disappeared, changed states etc.
|
||||
*/
|
||||
public class DictionaryListInterfaceState {
|
||||
private static class State {
|
||||
static class State {
|
||||
public boolean mOpen = false;
|
||||
public int mStatus = MetadataDbHelper.STATUS_UNKNOWN;
|
||||
}
|
||||
|
|
|
@ -255,10 +255,9 @@ public final class DictionaryProvider extends ContentProvider {
|
|||
if (null != dictFiles && dictFiles.size() > 0) {
|
||||
PrivateLog.log("Returned " + dictFiles.size() + " files");
|
||||
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()
|
||||
default:
|
||||
return null;
|
||||
|
@ -319,14 +318,13 @@ public final class DictionaryProvider extends ContentProvider {
|
|||
final AssetFileDescriptor afd = getContext().getResources().openRawResourceFd(
|
||||
R.raw.empty);
|
||||
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) {
|
||||
// No file : fall through and return null
|
||||
}
|
||||
|
@ -461,13 +459,16 @@ public final class DictionaryProvider extends ContentProvider {
|
|||
final String wordlistId = uri.getLastPathSegment();
|
||||
final String clientId = getClientId(uri);
|
||||
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 version = wordList.getAsInteger(MetadataDbHelper.VERSION_COLUMN);
|
||||
if (MetadataDbHelper.STATUS_DELETING == status) {
|
||||
UpdateHandler.markAsDeleted(getContext(), clientId, wordlistId, version, status);
|
||||
return 1;
|
||||
} else if (MetadataDbHelper.STATUS_INSTALLED == status) {
|
||||
}
|
||||
if (MetadataDbHelper.STATUS_INSTALLED == status) {
|
||||
final String result = uri.getQueryParameter(QUERY_PARAMETER_DELETE_RESULT);
|
||||
if (QUERY_PARAMETER_FAILURE.equals(result)) {
|
||||
if (DEBUG) {
|
||||
|
@ -480,15 +481,10 @@ public final class DictionaryProvider extends ContentProvider {
|
|||
wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
|
||||
final File f = getContext().getFileStreamPath(localFilename);
|
||||
// f.delete() returns true if the file was successfully deleted, false otherwise
|
||||
if (f.delete()) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Attempt to delete a file whose status is " + status);
|
||||
return 0;
|
||||
return f.delete() ? 1 : 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;
|
||||
}
|
||||
|
||||
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())) {
|
||||
// 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
|
||||
|
|
|
@ -31,7 +31,6 @@ import android.preference.Preference;
|
|||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
|
@ -203,25 +202,19 @@ public final class DictionarySettingsFragment extends PreferenceFragment
|
|||
@Override
|
||||
public void updateCycleCompleted() {}
|
||||
|
||||
private void refreshNetworkState() {
|
||||
void refreshNetworkState() {
|
||||
NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
|
||||
boolean isConnected = null == info ? false : info.isConnected();
|
||||
if (null != mUpdateNowMenu) mUpdateNowMenu.setEnabled(isConnected);
|
||||
}
|
||||
|
||||
private void refreshInterface() {
|
||||
void refreshInterface() {
|
||||
final Activity activity = getActivity();
|
||||
if (null == activity) return;
|
||||
final long lastUpdateDate =
|
||||
MetadataDbHelper.getLastUpdateDateForClient(getActivity(), mClientId);
|
||||
final PreferenceGroup prefScreen = getPreferenceScreen();
|
||||
final Collection<? extends Preference> prefList =
|
||||
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() {
|
||||
@Override
|
||||
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);
|
||||
message.setTitle(messageResource);
|
||||
message.setEnabled(false);
|
||||
return message;
|
||||
}
|
||||
|
||||
private void removeAnyDictSettings(final PreferenceGroup prefGroup) {
|
||||
static void removeAnyDictSettings(final PreferenceGroup prefGroup) {
|
||||
for (int i = prefGroup.getPreferenceCount() - 1; i >= 0; --i) {
|
||||
prefGroup.removePreference(prefGroup.getPreference(i));
|
||||
}
|
||||
|
@ -276,7 +269,7 @@ public final class DictionarySettingsFragment extends PreferenceFragment
|
|||
.appendQueryParameter(DictionaryProvider.QUERY_PARAMETER_PROTOCOL_VERSION, "2")
|
||||
.build();
|
||||
final Activity activity = getActivity();
|
||||
final Cursor cursor = null == activity ? null
|
||||
final Cursor cursor = (null == activity) ? null
|
||||
: activity.getContentResolver().query(contentUri, null, null, null, null);
|
||||
|
||||
if (null == cursor) {
|
||||
|
@ -289,61 +282,57 @@ public final class DictionarySettingsFragment extends PreferenceFragment
|
|||
final ArrayList<Preference> result = new ArrayList<>();
|
||||
result.add(createErrorMessage(activity, R.string.no_dictionaries_available));
|
||||
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 {
|
||||
cursor.close();
|
||||
}
|
||||
|
@ -396,26 +385,28 @@ public final class DictionarySettingsFragment extends PreferenceFragment
|
|||
if (null != mUpdateNowMenu) mUpdateNowMenu.setTitle(R.string.cancel);
|
||||
}
|
||||
|
||||
private void stopLoadingAnimation() {
|
||||
void stopLoadingAnimation() {
|
||||
final View preferenceView = getView();
|
||||
final Activity activity = getActivity();
|
||||
if (null == activity) return;
|
||||
final View loadingView = mLoadingView;
|
||||
final MenuItem updateNowMenu = mUpdateNowMenu;
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mLoadingView.setVisibility(View.GONE);
|
||||
preferenceView.setVisibility(View.VISIBLE);
|
||||
mLoadingView.startAnimation(AnimationUtils.loadAnimation(
|
||||
getActivity(), android.R.anim.fade_out));
|
||||
preferenceView.startAnimation(AnimationUtils.loadAnimation(
|
||||
getActivity(), android.R.anim.fade_in));
|
||||
// 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
|
||||
// created yet - hence the necessity for a null check here.
|
||||
if (null != mUpdateNowMenu) {
|
||||
mUpdateNowMenu.setTitle(R.string.check_for_updates_now);
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
loadingView.setVisibility(View.GONE);
|
||||
preferenceView.setVisibility(View.VISIBLE);
|
||||
loadingView.startAnimation(AnimationUtils.loadAnimation(
|
||||
activity, android.R.anim.fade_out));
|
||||
preferenceView.startAnimation(AnimationUtils.loadAnimation(
|
||||
activity, android.R.anim.fade_in));
|
||||
// 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
|
||||
// created yet - hence the necessity for a null check here.
|
||||
if (null != updateNowMenu) {
|
||||
updateNowMenu.setTitle(R.string.check_for_updates_now);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -226,7 +226,7 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
|
|||
createClientTable(db);
|
||||
}
|
||||
|
||||
private void addRawChecksumColumnUnlessPresent(final SQLiteDatabase db) {
|
||||
private static void addRawChecksumColumnUnlessPresent(final SQLiteDatabase db) {
|
||||
try {
|
||||
db.execSQL("SELECT " + RAW_CHECKSUM_COLUMN + " FROM "
|
||||
+ 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 {
|
||||
db.execSQL("SELECT " + RETRY_COUNT_COLUMN + " FROM "
|
||||
+ METADATA_TABLE_NAME + " LIMIT 0;");
|
||||
|
|
|
@ -30,9 +30,6 @@ import java.util.List;
|
|||
* Helper class to easy up manipulation of dictionary pack metadata.
|
||||
*/
|
||||
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
|
||||
// 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.
|
||||
|
|
|
@ -43,8 +43,8 @@ public class PrivateLog {
|
|||
+ COLUMN_DATE + " TEXT,"
|
||||
+ COLUMN_EVENT + " TEXT);";
|
||||
|
||||
private static final SimpleDateFormat sDateFormat =
|
||||
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US);
|
||||
static final SimpleDateFormat sDateFormat = new SimpleDateFormat(
|
||||
"yyyy/MM/dd HH:mm:ss", Locale.ROOT);
|
||||
|
||||
private static PrivateLog sInstance = new PrivateLog();
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ public class PrivateLog {
|
|||
insert(db, "Upgrade finished");
|
||||
}
|
||||
|
||||
private static void insert(SQLiteDatabase db, String event) {
|
||||
static void insert(SQLiteDatabase db, String event) {
|
||||
if (!DEBUG) return;
|
||||
final ContentValues c = new ContentValues(2);
|
||||
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.TreeSet;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Handler for the update process.
|
||||
*
|
||||
|
@ -750,19 +752,22 @@ public final class UpdateHandler {
|
|||
* @return an ordered list of runnables to be called to upgrade.
|
||||
*/
|
||||
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();
|
||||
// Upgrade existing word lists
|
||||
DebugLogUtils.l("Comparing dictionaries");
|
||||
final Set<String> wordListIds = new TreeSet<>();
|
||||
// TODO: Can these be null?
|
||||
if (null == from) from = new ArrayList<>();
|
||||
if (null == to) to = new ArrayList<>();
|
||||
for (WordListMetadata wlData : from) wordListIds.add(wlData.mId);
|
||||
for (WordListMetadata wlData : to) wordListIds.add(wlData.mId);
|
||||
final List<WordListMetadata> fromList = (from == null) ? new ArrayList<WordListMetadata>()
|
||||
: from;
|
||||
final List<WordListMetadata> toList = (to == null) ? new ArrayList<WordListMetadata>()
|
||||
: to;
|
||||
for (WordListMetadata wlData : fromList) wordListIds.add(wlData.mId);
|
||||
for (WordListMetadata wlData : toList) wordListIds.add(wlData.mId);
|
||||
for (String id : wordListIds) {
|
||||
final WordListMetadata currentInfo = MetadataHandler.findWordListById(from, id);
|
||||
final WordListMetadata metadataInfo = MetadataHandler.findWordListById(to, id);
|
||||
final WordListMetadata currentInfo = MetadataHandler.findWordListById(fromList, id);
|
||||
final WordListMetadata metadataInfo = MetadataHandler.findWordListById(toList, id);
|
||||
// TODO: Remove the following unnecessary check, since we are now doing the filtering
|
||||
// inside findWordListById.
|
||||
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.
|
||||
*/
|
||||
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
|
||||
// the content provider. Empty string sounds sensible.
|
||||
static final private String NO_STATUS_MESSAGE = "";
|
||||
private static final String NO_STATUS_MESSAGE = "";
|
||||
|
||||
/// Actions
|
||||
static final private int ACTION_UNKNOWN = 0;
|
||||
static final private int ACTION_ENABLE_DICT = 1;
|
||||
static final private int ACTION_DISABLE_DICT = 2;
|
||||
static final private int ACTION_DELETE_DICT = 3;
|
||||
private static final int ACTION_UNKNOWN = 0;
|
||||
private static final int ACTION_ENABLE_DICT = 1;
|
||||
private static final int ACTION_DISABLE_DICT = 2;
|
||||
private static final int ACTION_DELETE_DICT = 3;
|
||||
|
||||
// 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.
|
||||
public final String mWordlistId;
|
||||
public final int mVersion;
|
||||
public final Locale mLocale;
|
||||
public final String mDescription;
|
||||
|
||||
// The id of the client for which this preference is.
|
||||
private final String mClientId;
|
||||
// The status
|
||||
private int mStatus;
|
||||
// The size of the dictionary file
|
||||
private final int mFilesize;
|
||||
|
||||
private final DictionaryListInterfaceState mInterfaceState;
|
||||
private final OnWordListPreferenceClick mPreferenceClickHandler =
|
||||
new OnWordListPreferenceClick();
|
||||
private final OnActionButtonClick mActionButtonClickHandler =
|
||||
new OnActionButtonClick();
|
||||
|
||||
public WordListPreference(final Context context,
|
||||
final DictionaryListInterfaceState dictionaryListInterfaceState, final String clientId,
|
||||
final String wordlistId, final int version, final Locale locale,
|
||||
final String description, final int status, final int filesize) {
|
||||
super(context, null);
|
||||
mContext = context;
|
||||
mInterfaceState = dictionaryListInterfaceState;
|
||||
mClientId = clientId;
|
||||
mVersion = version;
|
||||
|
@ -116,22 +110,23 @@ public final class WordListPreference extends Preference {
|
|||
}
|
||||
|
||||
private String getSummary(final int status) {
|
||||
final Context context = getContext();
|
||||
switch (status) {
|
||||
// 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
|
||||
// the delayed deletion process between the dictionary pack and Android Keyboard
|
||||
// would only be confusing.
|
||||
case MetadataDbHelper.STATUS_DELETING:
|
||||
case MetadataDbHelper.STATUS_AVAILABLE:
|
||||
return mContext.getString(R.string.dictionary_available);
|
||||
case MetadataDbHelper.STATUS_DOWNLOADING:
|
||||
return mContext.getString(R.string.dictionary_downloading);
|
||||
case MetadataDbHelper.STATUS_INSTALLED:
|
||||
return mContext.getString(R.string.dictionary_installed);
|
||||
case MetadataDbHelper.STATUS_DISABLED:
|
||||
return mContext.getString(R.string.dictionary_disabled);
|
||||
default:
|
||||
return NO_STATUS_MESSAGE;
|
||||
// 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
|
||||
// the delayed deletion process between the dictionary pack and Android Keyboard
|
||||
// would only be confusing.
|
||||
case MetadataDbHelper.STATUS_DELETING:
|
||||
case MetadataDbHelper.STATUS_AVAILABLE:
|
||||
return context.getString(R.string.dictionary_available);
|
||||
case MetadataDbHelper.STATUS_DOWNLOADING:
|
||||
return context.getString(R.string.dictionary_downloading);
|
||||
case MetadataDbHelper.STATUS_INSTALLED:
|
||||
return context.getString(R.string.dictionary_installed);
|
||||
case MetadataDbHelper.STATUS_DISABLED:
|
||||
return context.getString(R.string.dictionary_disabled);
|
||||
default:
|
||||
return NO_STATUS_MESSAGE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,7 +149,7 @@ public final class WordListPreference extends Preference {
|
|||
{ ButtonSwitcher.STATUS_INSTALL, ACTION_ENABLE_DICT }
|
||||
};
|
||||
|
||||
private int getButtonSwitcherStatus(final int status) {
|
||||
static int getButtonSwitcherStatus(final int status) {
|
||||
if (status >= sStatusActionList.length) {
|
||||
Log.e(TAG, "Unknown status " + status);
|
||||
return ButtonSwitcher.STATUS_NO_BUTTON;
|
||||
|
@ -162,7 +157,7 @@ public final class WordListPreference extends Preference {
|
|||
return sStatusActionList[status][0];
|
||||
}
|
||||
|
||||
private static int getActionIdFromStatusAndMenuEntry(final int status) {
|
||||
static int getActionIdFromStatusAndMenuEntry(final int status) {
|
||||
if (status >= sStatusActionList.length) {
|
||||
Log.e(TAG, "Unknown status " + status);
|
||||
return ACTION_UNKNOWN;
|
||||
|
@ -171,9 +166,10 @@ public final class WordListPreference extends Preference {
|
|||
}
|
||||
|
||||
private void disableDict() {
|
||||
SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext);
|
||||
final Context context = getContext();
|
||||
final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context);
|
||||
CommonPreferences.disable(prefs, mWordlistId);
|
||||
UpdateHandler.markAsUnused(mContext, mClientId, mWordlistId, mVersion, mStatus);
|
||||
UpdateHandler.markAsUnused(context, mClientId, mWordlistId, mVersion, mStatus);
|
||||
if (MetadataDbHelper.STATUS_DOWNLOADING == mStatus) {
|
||||
setStatus(MetadataDbHelper.STATUS_AVAILABLE);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableDict() {
|
||||
SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext);
|
||||
final Context context = getContext();
|
||||
final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context);
|
||||
CommonPreferences.enable(prefs, mWordlistId);
|
||||
// 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) {
|
||||
setStatus(MetadataDbHelper.STATUS_DOWNLOADING);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteDict() {
|
||||
SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext);
|
||||
final Context context = getContext();
|
||||
final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context);
|
||||
CommonPreferences.disable(prefs, mWordlistId);
|
||||
setStatus(MetadataDbHelper.STATUS_DELETING);
|
||||
UpdateHandler.markAsDeleting(mContext, mClientId, mWordlistId, mVersion, mStatus);
|
||||
UpdateHandler.markAsDeleting(context, mClientId, mWordlistId, mVersion, mStatus);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -225,8 +225,8 @@ public final class WordListPreference extends Preference {
|
|||
status.setVisibility(showProgressBar ? View.INVISIBLE : View.VISIBLE);
|
||||
progressBar.setVisibility(showProgressBar ? View.VISIBLE : View.INVISIBLE);
|
||||
|
||||
final ButtonSwitcher buttonSwitcher =
|
||||
(ButtonSwitcher)view.findViewById(R.id.wordlist_button_switcher);
|
||||
final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)view.findViewById(
|
||||
R.id.wordlist_button_switcher);
|
||||
// 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.
|
||||
buttonSwitcher.reset(mInterfaceState);
|
||||
|
@ -244,63 +244,67 @@ public final class WordListPreference extends Preference {
|
|||
// The button is closed.
|
||||
buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON);
|
||||
}
|
||||
buttonSwitcher.setInternalOnClickListener(mActionButtonClickHandler);
|
||||
view.setOnClickListener(mPreferenceClickHandler);
|
||||
buttonSwitcher.setInternalOnClickListener(new View.OnClickListener() {
|
||||
@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 {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
// Note : v is the preference view
|
||||
final ViewParent parent = v.getParent();
|
||||
// Just in case something changed in the framework, test for the concrete class
|
||||
if (!(parent instanceof ListView)) return;
|
||||
final ListView listView = (ListView)parent;
|
||||
final int indexToOpen;
|
||||
// Close all first, we'll open back any item that needs to be open.
|
||||
final boolean wasOpen = mInterfaceState.isOpen(mWordlistId);
|
||||
mInterfaceState.closeAll();
|
||||
if (wasOpen) {
|
||||
// This button being shown. Take note that we don't want to open any button in the
|
||||
// loop below.
|
||||
indexToOpen = -1;
|
||||
void onWordListClicked(final View v) {
|
||||
// Note : v is the preference view
|
||||
final ViewParent parent = v.getParent();
|
||||
// Just in case something changed in the framework, test for the concrete class
|
||||
if (!(parent instanceof ListView)) return;
|
||||
final ListView listView = (ListView)parent;
|
||||
final int indexToOpen;
|
||||
// Close all first, we'll open back any item that needs to be open.
|
||||
final boolean wasOpen = mInterfaceState.isOpen(mWordlistId);
|
||||
mInterfaceState.closeAll();
|
||||
if (wasOpen) {
|
||||
// This button being shown. Take note that we don't want to open any button in the
|
||||
// loop below.
|
||||
indexToOpen = -1;
|
||||
} else {
|
||||
// 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 {
|
||||
// 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 {
|
||||
buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON);
|
||||
}
|
||||
buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class OnActionButtonClick implements View.OnClickListener {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
switch (getActionIdFromStatusAndMenuEntry(mStatus)) {
|
||||
case ACTION_ENABLE_DICT:
|
||||
enableDict();
|
||||
break;
|
||||
case ACTION_DISABLE_DICT:
|
||||
disableDict();
|
||||
break;
|
||||
case ACTION_DELETE_DICT:
|
||||
deleteDict();
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Unknown menu item pressed");
|
||||
}
|
||||
void onActionButtonClicked() {
|
||||
switch (getActionIdFromStatusAndMenuEntry(mStatus)) {
|
||||
case ACTION_ENABLE_DICT:
|
||||
enableDict();
|
||||
break;
|
||||
case ACTION_DISABLE_DICT:
|
||||
disableDict();
|
||||
break;
|
||||
case ACTION_DELETE_DICT:
|
||||
deleteDict();
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Unknown menu item pressed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ package com.android.inputmethod.event;
|
|||
|
||||
import android.text.TextUtils;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.KeyCharacterMap;
|
||||
|
||||
import com.android.inputmethod.latin.Constants;
|
||||
|
||||
|
@ -70,8 +69,8 @@ public class DeadKeyCombiner implements Combiner {
|
|||
/**
|
||||
* Maps Unicode combining diacritical to display-form dead key.
|
||||
*/
|
||||
private static final SparseIntArray sCombiningToAccent = new SparseIntArray();
|
||||
private static final SparseIntArray sAccentToCombining = new SparseIntArray();
|
||||
static final SparseIntArray sCombiningToAccent = new SparseIntArray();
|
||||
static final SparseIntArray sAccentToCombining = new SparseIntArray();
|
||||
static {
|
||||
// U+0300: COMBINING GRAVE ACCENT
|
||||
addCombining('\u0300', ACCENT_GRAVE);
|
||||
|
@ -217,21 +216,20 @@ public class DeadKeyCombiner implements Combiner {
|
|||
final StringBuilder mDeadSequence = new StringBuilder();
|
||||
|
||||
@Nonnull
|
||||
private Event createEventChainFromSequence(final @Nonnull CharSequence text,
|
||||
private static Event createEventChainFromSequence(final @Nonnull CharSequence text,
|
||||
final Event originalEvent) {
|
||||
if (text.length() <= 0) {
|
||||
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
|
||||
|
@ -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
|
||||
// simply returns the event as is. The majority of events will go through this path.
|
||||
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
|
||||
|
|
|
@ -21,6 +21,8 @@ import com.android.inputmethod.latin.Constants;
|
|||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||
import com.android.inputmethod.latin.utils.StringUtils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* 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,
|
||||
final int x, final int y, final boolean isKeyRepeat) {
|
||||
return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode, x, y,
|
||||
null /* suggestedWordInfo */, isKeyRepeat ? FLAG_REPEAT : FLAG_NONE, null);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static Event createHardwareKeypressEvent(final int codePoint, final int keyCode,
|
||||
final Event next, final boolean isKeyRepeat) {
|
||||
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}
|
||||
@ExternallyReferenced
|
||||
@Nonnull
|
||||
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.
|
||||
return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
|
||||
|
@ -163,6 +168,7 @@ public class Event {
|
|||
* @param codePoint the code point.
|
||||
* @return an event for this code point.
|
||||
*/
|
||||
@Nonnull
|
||||
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.
|
||||
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.
|
||||
* @return an event for this code point and coordinates.
|
||||
*/
|
||||
@Nonnull
|
||||
public static Event createEventForCodePointFromAlreadyTypedText(final int codePoint,
|
||||
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.
|
||||
|
@ -189,6 +196,7 @@ public class Event {
|
|||
* Creates an input event representing the manual pick of a suggestion.
|
||||
* @return an event for this suggestion pick.
|
||||
*/
|
||||
@Nonnull
|
||||
public static Event createSuggestionPickedEvent(final SuggestedWordInfo suggestedWordInfo) {
|
||||
return new Event(EVENT_TYPE_SUGGESTION_PICKED, suggestedWordInfo.mWord,
|
||||
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.
|
||||
* @return an event for this text.
|
||||
*/
|
||||
@Nonnull
|
||||
public static Event createSoftwareTextEvent(final CharSequence text, final int keyCode) {
|
||||
return new Event(EVENT_TYPE_SOFTWARE_GENERATED_STRING, text, NOT_A_CODE_POINT, keyCode,
|
||||
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
|
||||
|
@ -228,6 +237,7 @@ public class Event {
|
|||
* @param source the event to copy the properties of.
|
||||
* @return an identical event marked as consumed.
|
||||
*/
|
||||
@Nonnull
|
||||
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.
|
||||
return new Event(source.mEventType, source.mText, source.mCodePoint, source.mKeyCode,
|
||||
|
@ -235,6 +245,7 @@ public class Event {
|
|||
source.mNextEvent);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static Event createNotHandledEvent() {
|
||||
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,
|
||||
|
|
|
@ -67,10 +67,9 @@ public class HardwareKeyboardEventDecoder implements HardwareEventDecoder {
|
|||
if (keyEvent.isShiftPressed()) {
|
||||
return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT,
|
||||
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
|
||||
// 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.
|
||||
* @return the resulting software text event. Never null.
|
||||
*/
|
||||
@Nonnull
|
||||
private Event clearAndGetResultingEvent(final Event newEvent) {
|
||||
final CharSequence combinedText;
|
||||
if (mCurrentEvents.size() > 0) {
|
||||
|
@ -139,7 +140,8 @@ public class MyanmarReordering implements Combiner {
|
|||
if (null == lastEvent) {
|
||||
mCurrentEvents.add(newEvent);
|
||||
return Event.createConsumedEvent(newEvent);
|
||||
} else if (isConsonantOrMedial(lastEvent.mCodePoint)) {
|
||||
}
|
||||
if (isConsonantOrMedial(lastEvent.mCodePoint)) {
|
||||
final Event resultingEvent = clearAndGetResultingEvent(null);
|
||||
mCurrentEvents.add(Event.createSoftwareKeypressEvent(ZERO_WIDTH_NON_JOINER,
|
||||
Event.NOT_A_KEY_CODE,
|
||||
|
@ -147,15 +149,17 @@ public class MyanmarReordering implements Combiner {
|
|||
false /* isKeyRepeat */));
|
||||
mCurrentEvents.add(newEvent);
|
||||
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();
|
||||
if (null == lastEvent) {
|
||||
mCurrentEvents.add(newEvent);
|
||||
return Event.createConsumedEvent(newEvent);
|
||||
} else if (VOWEL_E == lastEvent.mCodePoint) {
|
||||
}
|
||||
if (VOWEL_E == lastEvent.mCodePoint) {
|
||||
final int eventSize = mCurrentEvents.size();
|
||||
if (eventSize >= 2
|
||||
&& mCurrentEvents.get(eventSize - 2).mCodePoint == ZERO_WIDTH_NON_JOINER) {
|
||||
|
@ -178,15 +182,17 @@ public class MyanmarReordering implements Combiner {
|
|||
mCurrentEvents.add(newEvent);
|
||||
mCurrentEvents.add(lastEvent);
|
||||
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();
|
||||
if (null == lastEvent) {
|
||||
mCurrentEvents.add(newEvent);
|
||||
return Event.createConsumedEvent(newEvent);
|
||||
} else if (VOWEL_E == lastEvent.mCodePoint) {
|
||||
}
|
||||
if (VOWEL_E == lastEvent.mCodePoint) {
|
||||
final int eventSize = mCurrentEvents.size();
|
||||
// If there is already a consonant, then we are in the middle of a syllable, and we
|
||||
// need to reorder.
|
||||
|
@ -205,37 +211,36 @@ public class MyanmarReordering implements Combiner {
|
|||
}
|
||||
// Otherwise, we just commit everything.
|
||||
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) {
|
||||
final Event lastEvent = getLastEvent();
|
||||
// lastCodePoint is a consonant/medial. But if it's something else it's fine
|
||||
return clearAndGetResultingEvent(newEvent);
|
||||
}
|
||||
final Event lastEvent = getLastEvent();
|
||||
if (Constants.CODE_DELETE == newEvent.mKeyCode && null != lastEvent) {
|
||||
final int eventSize = mCurrentEvents.size();
|
||||
if (null != lastEvent) {
|
||||
if (VOWEL_E == lastEvent.mCodePoint) {
|
||||
// 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 preceded by a ZWNJ. Remove both vowel E and ZWNJ.
|
||||
// - 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.
|
||||
if (eventSize <= 1) {
|
||||
mCurrentEvents.clear();
|
||||
} else { // eventSize >= 2
|
||||
final int previousCodePoint = mCurrentEvents.get(eventSize - 2).mCodePoint;
|
||||
if (previousCodePoint == ZERO_WIDTH_NON_JOINER) {
|
||||
mCurrentEvents.remove(eventSize - 1);
|
||||
mCurrentEvents.remove(eventSize - 2);
|
||||
} else if (isConsonantOrMedial(previousCodePoint)) {
|
||||
mCurrentEvents.remove(eventSize - 2);
|
||||
} else {
|
||||
mCurrentEvents.remove(eventSize - 1);
|
||||
}
|
||||
if (VOWEL_E == lastEvent.mCodePoint) {
|
||||
// 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 preceded by a ZWNJ. Remove both vowel E and ZWNJ.
|
||||
// - 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.
|
||||
if (eventSize <= 1) {
|
||||
mCurrentEvents.clear();
|
||||
} else { // eventSize >= 2
|
||||
final int previousCodePoint = mCurrentEvents.get(eventSize - 2).mCodePoint;
|
||||
if (previousCodePoint == ZERO_WIDTH_NON_JOINER) {
|
||||
mCurrentEvents.remove(eventSize - 1);
|
||||
mCurrentEvents.remove(eventSize - 2);
|
||||
} else if (isConsonantOrMedial(previousCodePoint)) {
|
||||
mCurrentEvents.remove(eventSize - 2);
|
||||
} else {
|
||||
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.
|
||||
|
@ -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.
|
||||
mCurrentEvents.add(newEvent);
|
||||
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
|
||||
|
|
|
@ -25,7 +25,6 @@ import android.view.inputmethod.EditorInfo;
|
|||
import com.android.inputmethod.compat.EditorInfoCompatUtils;
|
||||
import com.android.inputmethod.latin.RichInputMethodSubtype;
|
||||
import com.android.inputmethod.latin.utils.InputTypeUtils;
|
||||
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
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.SubtypeSwitcher;
|
||||
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.ScriptUtils;
|
||||
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
||||
|
@ -424,9 +423,8 @@ public final class KeyboardLayoutSet {
|
|||
final String tag = parser.getName();
|
||||
if (TAG_KEYBOARD_SET.equals(tag)) {
|
||||
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.
|
||||
@Override
|
||||
public void requestUpdatingShiftState(final int currentAutoCapsState,
|
||||
final int currentRecapitalizeState) {
|
||||
mState.onUpdateShiftState(currentAutoCapsState, currentRecapitalizeState);
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package com.android.inputmethod.keyboard;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.inputmethod.keyboard.internal.TouchPositionCorrection;
|
||||
|
|
|
@ -181,7 +181,7 @@ public class TextDecorator {
|
|||
layoutMain();
|
||||
}
|
||||
|
||||
private void layoutMain() {
|
||||
void layoutMain() {
|
||||
final CursorAnchorInfoCompatWrapper info = mCursorAnchorInfoWrapper;
|
||||
|
||||
if (info == null) {
|
||||
|
@ -289,7 +289,7 @@ public class TextDecorator {
|
|||
mHasRtlCharsInLastComposingText);
|
||||
}
|
||||
|
||||
private void onClickIndicator() {
|
||||
void onClickIndicator() {
|
||||
if (mMode != MODE_SHOWING_INDICATOR) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ final class EmojiCategory {
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -138,6 +138,21 @@ final class EmojiPageKeyboardView extends KeyboardView implements
|
|||
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) {
|
||||
mHandler.removeCallbacks(mPendingKeyDown);
|
||||
mPendingKeyDown = null;
|
||||
|
@ -145,11 +160,7 @@ final class EmojiPageKeyboardView extends KeyboardView implements
|
|||
if (currentKey == null) {
|
||||
return;
|
||||
}
|
||||
currentKey.onReleased();
|
||||
invalidateKey(currentKey);
|
||||
if (withKeyRegistering) {
|
||||
mListener.onReleaseKey(currentKey);
|
||||
}
|
||||
callListenerOnReleaseKey(currentKey, withKeyRegistering);
|
||||
mCurrentKey = null;
|
||||
}
|
||||
|
||||
|
@ -165,10 +176,7 @@ final class EmojiPageKeyboardView extends KeyboardView implements
|
|||
mPendingKeyDown = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mPendingKeyDown = null;
|
||||
key.onPressed();
|
||||
invalidateKey(key);
|
||||
mListener.onPressKey(key);
|
||||
callListenerOnPressKey(key);
|
||||
}
|
||||
};
|
||||
mHandler.postDelayed(mPendingKeyDown, KEY_PRESS_DELAY_TIME);
|
||||
|
@ -195,15 +203,11 @@ final class EmojiPageKeyboardView extends KeyboardView implements
|
|||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
key.onReleased();
|
||||
invalidateKey(key);
|
||||
mListener.onReleaseKey(key);
|
||||
callListenerOnReleaseKey(key, true /* withRegistering */);
|
||||
}
|
||||
}, KEY_RELEASE_DELAY_TIME);
|
||||
} else {
|
||||
key.onReleased();
|
||||
invalidateKey(key);
|
||||
mListener.onReleaseKey(key);
|
||||
callListenerOnReleaseKey(key, true /* withRegistering */);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
|
|||
}
|
||||
|
||||
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);
|
||||
tspec.setContent(R.id.emoji_keyboard_dummy);
|
||||
final ImageView iconView = (ImageView)LayoutInflater.from(getContext()).inflate(
|
||||
|
|
|
@ -148,7 +148,7 @@ public final class KeyPreviewChoreographer {
|
|||
keyPreviewView.setPivotY(previewHeight);
|
||||
}
|
||||
|
||||
private void showKeyPreview(final Key key, final KeyPreviewView keyPreviewView,
|
||||
void showKeyPreview(final Key key, final KeyPreviewView keyPreviewView,
|
||||
final boolean withAnimation) {
|
||||
if (!withAnimation) {
|
||||
keyPreviewView.setVisibility(View.VISIBLE);
|
||||
|
@ -166,25 +166,25 @@ public final class KeyPreviewChoreographer {
|
|||
}
|
||||
|
||||
public Animator createShowUpAnimator(final Key key, final KeyPreviewView keyPreviewView) {
|
||||
final Animator animator = mParams.createShowUpAnimator(keyPreviewView);
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
final Animator showUpAnimator = mParams.createShowUpAnimator(keyPreviewView);
|
||||
showUpAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(final Animator animator) {
|
||||
showKeyPreview(key, keyPreviewView, false /* withAnimation */);
|
||||
}
|
||||
});
|
||||
return animator;
|
||||
return showUpAnimator;
|
||||
}
|
||||
|
||||
private Animator createDismissAnimator(final Key key, final KeyPreviewView keyPreviewView) {
|
||||
final Animator animator = mParams.createDismissAnimator(keyPreviewView);
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
final Animator dismissAnimator = mParams.createDismissAnimator(keyPreviewView);
|
||||
dismissAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(final Animator animator) {
|
||||
dismissKeyPreview(key, false /* withAnimation */);
|
||||
}
|
||||
});
|
||||
return animator;
|
||||
return dismissAnimator;
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
return matchString(caseAttr, R.styleable.Keyboard_Case_languageCode,
|
||||
locales[0].getLanguage());
|
||||
}
|
||||
|
||||
private boolean matchCountryCodes(TypedArray caseAttr, Locale[] locales) {
|
||||
private static boolean matchCountryCodes(TypedArray caseAttr, Locale[] locales) {
|
||||
// TODO: adujst this for multilingual input
|
||||
return matchString(caseAttr, R.styleable.Keyboard_Case_countryCode,
|
||||
locales[0].getCountry());
|
||||
|
|
|
@ -28,7 +28,8 @@ import java.util.Arrays;
|
|||
*/
|
||||
@UsedForTesting
|
||||
public class MatrixUtils {
|
||||
private static final String TAG = MatrixUtils.class.getSimpleName();
|
||||
static final String TAG = MatrixUtils.class.getSimpleName();
|
||||
|
||||
public static class MatrixOperationFailedException extends Exception {
|
||||
private static final long serialVersionUID = 4384485606788583829L;
|
||||
|
||||
|
|
|
@ -108,9 +108,8 @@ public final class MoreKeySpec {
|
|||
: Constants.printableCode(mCode));
|
||||
if (StringUtils.codePointCount(label) == 1 && label.codePointAt(0) == mCode) {
|
||||
return output;
|
||||
} else {
|
||||
return label + "|" + output;
|
||||
}
|
||||
return label + "|" + output;
|
||||
}
|
||||
|
||||
public static class LettersOnBaseLayout {
|
||||
|
|
|
@ -80,6 +80,7 @@ public final class TouchPositionCorrection {
|
|||
return mRadii.length;
|
||||
}
|
||||
|
||||
@SuppressWarnings("static-method")
|
||||
public float getX(final int row) {
|
||||
return 0.0f;
|
||||
// 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
|
||||
// found anymore it's safer to actually supply installed dictionaries.
|
||||
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.ContactsContract;
|
||||
import android.provider.ContactsContract.Contacts;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
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.
|
||||
if (locale != null && locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
|
||||
return true;
|
||||
|
@ -269,7 +268,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
|
|||
return end;
|
||||
}
|
||||
|
||||
private boolean haveContentsChanged() {
|
||||
boolean haveContentsChanged() {
|
||||
final long startTime = SystemClock.uptimeMillis();
|
||||
final int contactCount = getContactCount();
|
||||
if (contactCount > MAX_CONTACT_COUNT) {
|
||||
|
|
|
@ -70,7 +70,7 @@ public final class DicTraverseSession {
|
|||
mNativeDicTraverseSession, dictionary, previousWord, previousWordLength);
|
||||
}
|
||||
|
||||
private final long createNativeDicTraverseSession(String locale, long dictSize) {
|
||||
private static long createNativeDicTraverseSession(String locale, long 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,
|
||||
* e.g., the user's contacts.
|
||||
*/
|
||||
private static final HashSet<String> sUserSpecificDictionaryTypes =
|
||||
new HashSet(Arrays.asList(new String[] { TYPE_USER_TYPED, TYPE_USER, TYPE_CONTACTS,
|
||||
TYPE_USER_HISTORY, TYPE_PERSONALIZATION, TYPE_CONTEXTUAL }));
|
||||
private static final HashSet<String> sUserSpecificDictionaryTypes = new HashSet<>(Arrays.asList(
|
||||
TYPE_USER_TYPED,
|
||||
TYPE_USER,
|
||||
TYPE_CONTACTS,
|
||||
TYPE_USER_HISTORY,
|
||||
TYPE_PERSONALIZATION,
|
||||
TYPE_CONTEXTUAL));
|
||||
|
||||
public Dictionary(final String dictType, final Locale locale) {
|
||||
mDictType = dictType;
|
||||
|
|
|
@ -172,9 +172,8 @@ public class DictionaryFacilitator {
|
|||
public Dictionary getDict(final String dictType) {
|
||||
if (Dictionary.TYPE_MAIN.equals(dictType)) {
|
||||
return mMainDict;
|
||||
} else {
|
||||
return getSubDict(dictType);
|
||||
}
|
||||
return getSubDict(dictType);
|
||||
}
|
||||
|
||||
public ExpandableBinaryDictionary getSubDict(final String dictType) {
|
||||
|
@ -184,9 +183,8 @@ public class DictionaryFacilitator {
|
|||
public boolean hasDict(final String dictType) {
|
||||
if (Dictionary.TYPE_MAIN.equals(dictType)) {
|
||||
return mMainDict != null;
|
||||
} else {
|
||||
return mSubDictMap.containsKey(dictType);
|
||||
}
|
||||
return mSubDictMap.containsKey(dictType);
|
||||
}
|
||||
|
||||
public void closeDict(final String dictType) {
|
||||
|
@ -305,7 +303,7 @@ public class DictionaryFacilitator {
|
|||
usePersonalizedDicts, forceReloadMainDictionary, listener, "" /* dictNamePrefix */);
|
||||
}
|
||||
|
||||
private DictionaryGroup findDictionaryGroupWithLocale(final DictionaryGroup[] dictionaryGroups,
|
||||
static DictionaryGroup findDictionaryGroupWithLocale(final DictionaryGroup[] dictionaryGroups,
|
||||
final Locale locale) {
|
||||
for (int i = 0; i < dictionaryGroups.length; ++i) {
|
||||
if (locale.equals(dictionaryGroups[i].mLocale)) {
|
||||
|
@ -422,34 +420,41 @@ public class DictionaryFacilitator {
|
|||
ExecutorUtils.getExecutor("InitializeBinaryDictionary").execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
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();
|
||||
doReloadUninitializedMainDictionaries(
|
||||
context, locales, listener, latchForWaitingLoadingMainDictionary);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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
|
||||
public void resetDictionariesForTesting(final Context context, final Locale[] locales,
|
||||
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.
|
||||
*/
|
||||
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 MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT = 5;
|
||||
|
||||
|
@ -81,7 +81,8 @@ public class DictionaryFacilitatorLruCache {
|
|||
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++) {
|
||||
try {
|
||||
dictionaryFacilitator.waitForLoadingMainDictionaries(
|
||||
|
|
|
@ -21,11 +21,11 @@ import android.util.Log;
|
|||
|
||||
import com.android.inputmethod.annotations.UsedForTesting;
|
||||
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.FormatSpec;
|
||||
import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
|
||||
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.utils.AsyncResultHolder;
|
||||
import com.android.inputmethod.latin.utils.CombinedFormatUtils;
|
||||
|
@ -47,6 +47,7 @@ import java.util.concurrent.locks.Lock;
|
|||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
private boolean matchesExpectedBinaryDictFormatVersionForThisType(final int formatVersion) {
|
||||
static boolean matchesExpectedBinaryDictFormatVersionForThisType(final int formatVersion) {
|
||||
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
|
||||
// for supporting migration. Note that native code has to support reading such formats.
|
||||
return formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING;
|
||||
|
@ -159,7 +160,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
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) {
|
||||
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.
|
||||
private void asyncPreCheckAndExecuteTaskWithLock(final Lock lock,
|
||||
private static void asyncPreCheckAndExecuteTaskWithLock(final Lock lock,
|
||||
final Callable<Boolean> preCheckTask, final String executorName, final Runnable task) {
|
||||
final String tag = TAG;
|
||||
ExecutorUtils.getExecutor(executorName).execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -183,7 +185,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
return;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -205,10 +219,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
asyncExecuteTaskWithWriteLock(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mBinaryDictionary != null) {
|
||||
mBinaryDictionary.close();
|
||||
mBinaryDictionary = null;
|
||||
}
|
||||
closeBinaryDictionary();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -234,14 +245,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
});
|
||||
}
|
||||
|
||||
private void removeBinaryDictionaryLocked() {
|
||||
if (mBinaryDictionary != null) {
|
||||
mBinaryDictionary.close();
|
||||
}
|
||||
void removeBinaryDictionaryLocked() {
|
||||
closeBinaryDictionary();
|
||||
if (mDictFile.exists() && !FileUtils.deleteRecursively(mDictFile)) {
|
||||
Log.e(TAG, "Can't remove a file: " + mDictFile.getName());
|
||||
}
|
||||
mBinaryDictionary = null;
|
||||
}
|
||||
|
||||
private void openBinaryDictionaryLocked() {
|
||||
|
@ -250,7 +258,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
true /* useFullEditDistance */, mLocale, mDictType, true /* isUpdatable */);
|
||||
}
|
||||
|
||||
private void createOnMemoryBinaryDictionaryLocked() {
|
||||
void createOnMemoryBinaryDictionaryLocked() {
|
||||
mBinaryDictionary = new BinaryDictionary(
|
||||
mDictFile.getAbsolutePath(), true /* useFullEditDistance */, mLocale, mDictType,
|
||||
DICTIONARY_FORMAT_VERSION, getHeaderAttributeMap());
|
||||
|
@ -273,7 +281,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
asyncExecuteTaskWithWriteLock(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mBinaryDictionary == null) {
|
||||
if (getBinaryDictionary() == null) {
|
||||
return;
|
||||
}
|
||||
runGCIfRequiredLocked(mindsBlockByGC);
|
||||
|
@ -291,24 +299,24 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
@Nonnull final Runnable updateTask,
|
||||
@Nonnull final String word, @Nonnull final DistracterFilter distracterFilter) {
|
||||
reloadDictionaryIfRequired();
|
||||
asyncPreCheckAndExecuteTaskWithWriteLock(
|
||||
new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() throws Exception {
|
||||
return !distracterFilter.isDistracterToWordsInDictionaries(
|
||||
NgramContext.EMPTY_PREV_WORDS_INFO, word, mLocale);
|
||||
}
|
||||
},
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mBinaryDictionary == null) {
|
||||
return;
|
||||
}
|
||||
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
||||
updateTask.run();
|
||||
}
|
||||
});
|
||||
final Callable<Boolean> preCheckTask = new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() throws Exception {
|
||||
return !distracterFilter.isDistracterToWordsInDictionaries(
|
||||
NgramContext.EMPTY_PREV_WORDS_INFO, word, mLocale);
|
||||
}
|
||||
};
|
||||
final Runnable task = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (getBinaryDictionary() == null) {
|
||||
return;
|
||||
}
|
||||
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
||||
updateTask.run();
|
||||
}
|
||||
};
|
||||
asyncPreCheckAndExecuteTaskWithWriteLock(preCheckTask, task);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -344,11 +352,12 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
asyncExecuteTaskWithWriteLock(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mBinaryDictionary == null) {
|
||||
final BinaryDictionary binaryDictionary = getBinaryDictionary();
|
||||
if (binaryDictionary == null) {
|
||||
return;
|
||||
}
|
||||
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
||||
if (!mBinaryDictionary.removeUnigramEntry(word)) {
|
||||
if (!binaryDictionary.removeUnigramEntry(word)) {
|
||||
if (DEBUG) {
|
||||
Log.i(TAG, "Cannot remove unigram entry: " + word);
|
||||
}
|
||||
|
@ -366,7 +375,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
asyncExecuteTaskWithWriteLock(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mBinaryDictionary == null) {
|
||||
if (getBinaryDictionary() == null) {
|
||||
return;
|
||||
}
|
||||
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
||||
|
@ -395,11 +404,12 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
asyncExecuteTaskWithWriteLock(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mBinaryDictionary == null) {
|
||||
final BinaryDictionary binaryDictionary = getBinaryDictionary();
|
||||
if (binaryDictionary == null) {
|
||||
return;
|
||||
}
|
||||
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
||||
if (!mBinaryDictionary.removeNgramEntry(ngramContext, word)) {
|
||||
if (!binaryDictionary.removeNgramEntry(ngramContext, word)) {
|
||||
if (DEBUG) {
|
||||
Log.i(TAG, "Cannot remove n-gram entry.");
|
||||
Log.i(TAG, " NgramContext: " + ngramContext + ", word: " + word);
|
||||
|
@ -418,7 +428,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
updateDictionaryWithWriteLockIfWordIsNotADistracter(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!mBinaryDictionary.updateEntriesForWordWithNgramContext(ngramContext, word,
|
||||
final BinaryDictionary binaryDictionary = getBinaryDictionary();
|
||||
if (binaryDictionary == null) {
|
||||
return;
|
||||
}
|
||||
if (!binaryDictionary.updateEntriesForWordWithNgramContext(ngramContext, word,
|
||||
isValidWord, count, timestamp)) {
|
||||
if (DEBUG) {
|
||||
Log.e(TAG, "Cannot update counter. word: " + word
|
||||
|
@ -444,10 +458,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (mBinaryDictionary == null) {
|
||||
final BinaryDictionary binaryDictionary = getBinaryDictionary();
|
||||
if (binaryDictionary == null) {
|
||||
return;
|
||||
}
|
||||
mBinaryDictionary.addMultipleDictionaryEntries(
|
||||
binaryDictionary.addMultipleDictionaryEntries(
|
||||
languageModelParams.toArray(
|
||||
new LanguageModelParam[languageModelParams.size()]));
|
||||
} finally {
|
||||
|
@ -555,7 +570,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
* Loads the current binary dictionary from internal storage. Assumes the dictionary file
|
||||
* exists.
|
||||
*/
|
||||
private void loadBinaryDictionaryLocked() {
|
||||
void loadBinaryDictionaryLocked() {
|
||||
if (DBG_STRESS_TEST) {
|
||||
// Test if this class does not cause problems when it takes long time to load binary
|
||||
// dictionary.
|
||||
|
@ -583,7 +598,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
/**
|
||||
* Create a new binary dictionary and load initial contents.
|
||||
*/
|
||||
private void createNewDictionaryLocked() {
|
||||
void createNewDictionaryLocked() {
|
||||
removeBinaryDictionaryLocked();
|
||||
createOnMemoryBinaryDictionaryLocked();
|
||||
loadInitialContentsLocked();
|
||||
|
@ -599,6 +614,14 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
mNeedsToRecreate = true;
|
||||
}
|
||||
|
||||
void clearNeedsToRecreate() {
|
||||
mNeedsToRecreate = false;
|
||||
}
|
||||
|
||||
boolean isNeededToRecreate() {
|
||||
return mNeedsToRecreate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -621,35 +644,39 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
* Reloads the dictionary. Access is controlled on a per dictionary file basis.
|
||||
*/
|
||||
private final void asyncReloadDictionary() {
|
||||
if (mIsReloading.compareAndSet(false, true)) {
|
||||
asyncExecuteTaskWithWriteLock(new Runnable() {
|
||||
@Override
|
||||
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 AtomicBoolean isReloading = mIsReloading;
|
||||
if (!isReloading.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
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() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mBinaryDictionary == null) {
|
||||
final BinaryDictionary binaryDictionary = getBinaryDictionary();
|
||||
if (binaryDictionary == null) {
|
||||
return;
|
||||
}
|
||||
if (mBinaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
|
||||
mBinaryDictionary.flushWithGC();
|
||||
if (binaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
|
||||
binaryDictionary.flushWithGC();
|
||||
} else {
|
||||
mBinaryDictionary.flush();
|
||||
binaryDictionary.flush();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static int parseEntryCount(final String entryCountStr) {
|
||||
static int parseEntryCount(final String entryCountStr) {
|
||||
int entryCount;
|
||||
try {
|
||||
entryCount = Integer.parseInt(entryCountStr);
|
||||
|
@ -683,23 +711,27 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
|
||||
public DictionaryStats getDictionaryStats() {
|
||||
reloadDictionaryIfRequired();
|
||||
final String dictName = mDictName;
|
||||
final File dictFile = mDictFile;
|
||||
final AsyncResultHolder<DictionaryStats> result = new AsyncResultHolder<>();
|
||||
asyncExecuteTaskWithLock(mLock.readLock(), mDictName /* executorName */, new Runnable() {
|
||||
asyncExecuteTaskWithLock(mLock.readLock(), dictName /* executorName */, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mBinaryDictionary == null) {
|
||||
result.set(new DictionaryStats(mLocale, mDictName, mDictFile,
|
||||
final BinaryDictionary binaryDictionary = getBinaryDictionary();
|
||||
if (binaryDictionary == null) {
|
||||
result.set(new DictionaryStats(mLocale, dictName, dictFile,
|
||||
DictionaryStats.NOT_AN_ENTRY_COUNT,
|
||||
DictionaryStats.NOT_AN_ENTRY_COUNT));
|
||||
return;
|
||||
}
|
||||
final int unigramCount = parseEntryCount(
|
||||
mBinaryDictionary.getPropertyForGettingStats(
|
||||
binaryDictionary.getPropertyForGettingStats(
|
||||
BinaryDictionary.MAX_UNIGRAM_COUNT_QUERY));
|
||||
// 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));
|
||||
// TODO: Get more information from dictionary.
|
||||
result.set(new DictionaryStats(mLocale, mDictName, mDictFile, unigramCount,
|
||||
result.set(new DictionaryStats(mLocale, dictName, dictFile, unigramCount,
|
||||
ngramCount));
|
||||
}
|
||||
});
|
||||
|
@ -731,28 +763,34 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
|
||||
public void dumpAllWordsForDebug() {
|
||||
reloadDictionaryIfRequired();
|
||||
final String tag = TAG;
|
||||
final String dictName = mDictName;
|
||||
asyncExecuteTaskWithLock(mLock.readLock(), "dumpAllWordsForDebug", new Runnable() {
|
||||
@Override
|
||||
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 {
|
||||
final DictionaryHeader header = mBinaryDictionary.getHeader();
|
||||
Log.d(TAG, "Format version: " + mBinaryDictionary.getFormatVersion());
|
||||
Log.d(TAG, CombinedFormatUtils.formatAttributeMap(
|
||||
final DictionaryHeader header = binaryDictionary.getHeader();
|
||||
Log.d(tag, "Format version: " + binaryDictionary.getFormatVersion());
|
||||
Log.d(tag, CombinedFormatUtils.formatAttributeMap(
|
||||
header.mDictionaryOptions.mAttributes));
|
||||
} catch (final UnsupportedFormatException e) {
|
||||
Log.d(TAG, "Cannot fetch header information.", e);
|
||||
Log.d(tag, "Cannot fetch header information.", e);
|
||||
}
|
||||
int token = 0;
|
||||
do {
|
||||
final BinaryDictionary.GetNextWordPropertyResult result =
|
||||
mBinaryDictionary.getNextWordProperty(token);
|
||||
binaryDictionary.getNextWordProperty(token);
|
||||
final WordProperty wordProperty = result.mWordProperty;
|
||||
if (wordProperty == null) {
|
||||
Log.d(TAG, " dictionary is empty.");
|
||||
Log.d(tag, " dictionary is empty.");
|
||||
break;
|
||||
}
|
||||
Log.d(TAG, wordProperty.toString());
|
||||
Log.d(tag, wordProperty.toString());
|
||||
token = result.mNextToken;
|
||||
} while (token != 0);
|
||||
}
|
||||
|
|
|
@ -119,15 +119,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
SuggestionStripView.Listener, SuggestionStripViewAccessor,
|
||||
DictionaryFacilitator.DictionaryInitializationListener,
|
||||
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 boolean DEBUG = false;
|
||||
|
||||
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 PENDING_IMS_CALLBACK_DURATION_MILLIS = 800;
|
||||
private 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_WAIT_FOR_DICTIONARY_LOAD_MILLIS = TimeUnit.SECONDS.toMillis(2);
|
||||
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,
|
||||
|
@ -135,7 +135,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
*/
|
||||
private static final String SCHEME_PACKAGE = "package";
|
||||
|
||||
private final Settings mSettings;
|
||||
final Settings mSettings;
|
||||
private final DictionaryFacilitator mDictionaryFacilitator =
|
||||
new DictionaryFacilitator(this /* context */);
|
||||
// TODO: Move from LatinIME.
|
||||
|
@ -149,7 +149,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
mHandler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE);
|
||||
}
|
||||
});
|
||||
private final InputLogic mInputLogic = new InputLogic(this /* LatinIME */,
|
||||
final InputLogic mInputLogic = new InputLogic(this /* LatinIME */,
|
||||
this /* SuggestionStripViewAccessor */, mDictionaryFacilitator);
|
||||
// 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.
|
||||
|
@ -163,7 +163,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
|
||||
private RichInputMethodManager mRichImm;
|
||||
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
|
||||
private final SubtypeSwitcher mSubtypeSwitcher;
|
||||
final SubtypeSwitcher mSubtypeSwitcher;
|
||||
private final SubtypeState mSubtypeState = new SubtypeState();
|
||||
private final SpecialKeyDetector mSpecialKeyDetector;
|
||||
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_SHOW_GESTURE_FLOATING_PREVIEW_TEXT = 2;
|
||||
private static final int ARG2_UNUSED = 0;
|
||||
private static final int ARG1_FALSE = 0;
|
||||
private static final int ARG1_TRUE = 1;
|
||||
|
||||
private int mDelayInMillisecondsToUpdateSuggestions;
|
||||
|
@ -654,7 +653,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
}
|
||||
}
|
||||
|
||||
private void resetDictionaryFacilitatorIfNecessary() {
|
||||
void resetDictionaryFacilitatorIfNecessary() {
|
||||
final Locale[] subtypeSwitcherLocales = mSubtypeSwitcher.getCurrentSubtypeLocales();
|
||||
if (mDictionaryFacilitator.isForLocales(subtypeSwitcherLocales)) {
|
||||
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 =
|
||||
new ViewTreeObserver.OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
updateCursorAnchorInfo();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -846,12 +849,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
loadKeyboard();
|
||||
}
|
||||
|
||||
private void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {
|
||||
void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {
|
||||
super.onStartInput(editorInfo, restarting);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) {
|
||||
void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) {
|
||||
super.onStartInputView(editorInfo, restarting);
|
||||
// Switch to the null consumer to handle cases leading to early exit below, for which we
|
||||
// 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();
|
||||
|
||||
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);
|
||||
cleanupInternalStateForFinishInput();
|
||||
}
|
||||
|
@ -1295,11 +1298,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
}
|
||||
}
|
||||
|
||||
private int getCurrentAutoCapsState() {
|
||||
int getCurrentAutoCapsState() {
|
||||
return mInputLogic.getCurrentAutoCapsState(mSettings.getCurrent());
|
||||
}
|
||||
|
||||
private int getCurrentRecapitalizeState() {
|
||||
int getCurrentRecapitalizeState() {
|
||||
return mInputLogic.getCurrentRecapitalizeState();
|
||||
}
|
||||
|
||||
|
@ -1389,12 +1392,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
final Keyboard currentKeyboard = mKeyboardSwitcher.getKeyboard();
|
||||
if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) {
|
||||
return codePoint;
|
||||
} else {
|
||||
return Constants.CODE_SYMBOL_SHIFT;
|
||||
}
|
||||
} else {
|
||||
return codePoint;
|
||||
return Constants.CODE_SYMBOL_SHIFT;
|
||||
}
|
||||
return codePoint;
|
||||
}
|
||||
|
||||
// Implementation of {@link KeyboardActionListener}.
|
||||
|
@ -1496,7 +1497,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
}
|
||||
|
||||
// This method must run on the UI Thread.
|
||||
private void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords,
|
||||
void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords,
|
||||
final boolean dismissGestureFloatingPreviewText) {
|
||||
showSuggestionStrip(suggestedWords);
|
||||
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);
|
||||
requestHideSelf(0);
|
||||
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
|
||||
|
@ -1836,6 +1837,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
languageSelectionTitle,
|
||||
getString(ApplicationUtils.getActivityTitleResId(this, SettingsActivity.class))
|
||||
};
|
||||
final String imeId = mRichImm.getInputMethodIdOfThisIme();
|
||||
final OnClickListener listener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface di, int position) {
|
||||
|
@ -1843,7 +1845,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
switch (position) {
|
||||
case 0:
|
||||
final Intent intent = IntentUtils.getInputLanguageSelectionIntent(
|
||||
mRichImm.getInputMethodIdOfThisIme(),
|
||||
imeId,
|
||||
Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
|
||||
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
|
|
|
@ -31,14 +31,14 @@ public class NgramContext {
|
|||
public static final NgramContext EMPTY_PREV_WORDS_INFO =
|
||||
new NgramContext(WordInfo.EMPTY_WORD_INFO);
|
||||
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.
|
||||
*/
|
||||
public static class WordInfo {
|
||||
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.
|
||||
public final CharSequence mWord;
|
||||
|
@ -48,7 +48,7 @@ public class NgramContext {
|
|||
public final boolean mIsBeginningOfSentence;
|
||||
|
||||
// Beginning of sentence.
|
||||
public WordInfo() {
|
||||
private WordInfo() {
|
||||
mWord = "";
|
||||
mIsBeginningOfSentence = true;
|
||||
}
|
||||
|
@ -96,18 +96,6 @@ public class NgramContext {
|
|||
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.
|
||||
public NgramContext getNextNgramContext(final WordInfo wordInfo) {
|
||||
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.TextRange;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* {@link #commitTextWithBackgroundColor(CharSequence, int, int)} to avoid object creation.
|
||||
* {@link #commitTextWithBackgroundColor(CharSequence,int,int,int)} to avoid object creation.
|
||||
*/
|
||||
private SpannableStringBuilder mTempObjectForCommitText = new SpannableStringBuilder();
|
||||
/**
|
||||
|
@ -151,9 +149,8 @@ public final class RichInputConnection implements PrivateCommandPerformer {
|
|||
} else {
|
||||
if (DBG) {
|
||||
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_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
|
||||
// MODE_CHARACTERS and MODE_WORDS on.
|
||||
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
|
||||
// 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);
|
||||
}
|
||||
|
||||
private static boolean isSeparator(final int code, final int[] sortedSeparators) {
|
||||
return Arrays.binarySearch(sortedSeparators, code) >= 0;
|
||||
}
|
||||
|
||||
private static boolean isPartOfCompositionForScript(final int codePoint,
|
||||
final SpacingAndPunctuations spacingAndPunctuations, final int scriptId) {
|
||||
// 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
|
||||
* {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)} is currently enabled.
|
||||
* {@link InputMethodService#onUpdateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo)}
|
||||
* is currently enabled.
|
||||
*/
|
||||
public boolean isCursorAnchorInfoMonitorEnabled() {
|
||||
return mCursorAnchorInfoMonitorEnabled;
|
||||
|
|
|
@ -20,7 +20,6 @@ import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
|
|
|
@ -291,8 +291,9 @@ public final class SubtypeSwitcher {
|
|||
}
|
||||
|
||||
private static RichInputMethodSubtype sForcedSubtypeForTesting = null;
|
||||
|
||||
@UsedForTesting
|
||||
void forceSubtype(final InputMethodSubtype subtype) {
|
||||
static void forceSubtype(final InputMethodSubtype subtype) {
|
||||
sForcedSubtypeForTesting = new RichInputMethodSubtype(subtype);
|
||||
}
|
||||
|
||||
|
|
|
@ -328,7 +328,7 @@ public final class Suggest {
|
|||
* @param info the suggestion info
|
||||
* @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;
|
||||
if (null == locale) {
|
||||
return true;
|
||||
|
|
|
@ -365,9 +365,8 @@ public class SuggestedWords {
|
|||
public String toString() {
|
||||
if (TextUtils.isEmpty(mDebugString)) {
|
||||
return mWord;
|
||||
} else {
|
||||
return mWord + " (" + mDebugString + ")";
|
||||
}
|
||||
return mWord + " (" + mDebugString + ")";
|
||||
}
|
||||
|
||||
// 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 ContentObserver mObserver;
|
||||
final private String mLocale;
|
||||
final private String mLocaleString;
|
||||
final private boolean mAlsoUseMoreRestrictiveLocales;
|
||||
|
||||
protected UserBinaryDictionary(final Context context, final Locale locale,
|
||||
|
@ -74,9 +74,9 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
|
|||
final String localeStr = locale.toString();
|
||||
if (SubtypeLocaleUtils.NO_LANGUAGE.equals(localeStr)) {
|
||||
// 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 {
|
||||
mLocale = localeStr;
|
||||
mLocaleString = localeStr;
|
||||
}
|
||||
mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales;
|
||||
ContentResolver cres = context.getContentResolver();
|
||||
|
@ -124,7 +124,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
|
|||
// This is correct for locale processing.
|
||||
// For this example, we'll look at the "en_US_POSIX" case.
|
||||
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 StringBuilder request = new StringBuilder("(locale is NULL)");
|
||||
|
@ -207,9 +207,8 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
|
|||
if (client != null) {
|
||||
client.release();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -227,17 +226,16 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
|
|||
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.
|
||||
// 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.
|
||||
if (defaultFrequency > Integer.MAX_VALUE / LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY) {
|
||||
return (defaultFrequency / HISTORICAL_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) {
|
||||
|
|
|
@ -353,9 +353,8 @@ public final class WordComposer {
|
|||
if (size() <= 1) {
|
||||
return mCapitalizedMode == CAPS_MODE_AUTO_SHIFT_LOCKED
|
||||
|| mCapitalizedMode == CAPS_MODE_MANUAL_SHIFT_LOCKED;
|
||||
} else {
|
||||
return mCapsCount == size();
|
||||
}
|
||||
return mCapsCount == size();
|
||||
}
|
||||
|
||||
public boolean wasShiftedNoLock() {
|
||||
|
|
|
@ -44,7 +44,7 @@ import java.util.Locale;
|
|||
* A class to read a local file as a dictionary for debugging purposes.
|
||||
*/
|
||||
public class ExternalDictionaryGetterForDebug {
|
||||
private static final String SOURCE_FOLDER = Environment.getExternalStorageDirectory().getPath()
|
||||
static final String SOURCE_FOLDER = Environment.getExternalStorageDirectory().getPath()
|
||||
+ "/Download";
|
||||
|
||||
private static String[] findDictionariesInTheDownloadedFolder() {
|
||||
|
@ -142,8 +142,7 @@ public class ExternalDictionaryGetterForDebug {
|
|||
}).create().show();
|
||||
}
|
||||
|
||||
private static void installFile(final Context context, final File file,
|
||||
final DictionaryHeader header) {
|
||||
static void installFile(final Context context, final File file, final DictionaryHeader header) {
|
||||
BufferedOutputStream outputStream = null;
|
||||
File tempFile = null;
|
||||
try {
|
||||
|
|
|
@ -75,7 +75,7 @@ public final class InputLogic {
|
|||
private static final String TAG = InputLogic.class.getSimpleName();
|
||||
|
||||
// TODO : Remove this member when we can.
|
||||
private final LatinIME mLatinIME;
|
||||
final LatinIME mLatinIME;
|
||||
private final SuggestionStripViewAccessor mSuggestionStripViewAccessor;
|
||||
|
||||
// Never null.
|
||||
|
@ -1512,12 +1512,6 @@ public final class InputLogic {
|
|||
}
|
||||
}
|
||||
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,
|
||||
mLatinIME.getCoordinatesForCurrentKeyboard(codePoints));
|
||||
mWordComposer.setCursorPositionWithinWord(
|
||||
|
@ -1533,8 +1527,7 @@ public final class InputLogic {
|
|||
SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {
|
||||
@Override
|
||||
public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
|
||||
mIsAutoCorrectionIndicatorOn = false;
|
||||
mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
|
||||
doShowSuggestionsAndClearAutoCorrectionIndicator(suggestedWords);
|
||||
}});
|
||||
} else {
|
||||
// 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 */,
|
||||
false /* willAutoCorrect */, false /* isObsoleteSuggestions */,
|
||||
SuggestedWords.INPUT_STYLE_RECORRECTION, SuggestedWords.NOT_A_SEQUENCE_NUMBER);
|
||||
mIsAutoCorrectionIndicatorOn = false;
|
||||
mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
|
||||
doShowSuggestionsAndClearAutoCorrectionIndicator(suggestedWords);
|
||||
}
|
||||
}
|
||||
|
||||
void doShowSuggestionsAndClearAutoCorrectionIndicator(final SuggestedWords suggestedWords) {
|
||||
mIsAutoCorrectionIndicatorOn = false;
|
||||
mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverts a previous commit with auto-correction.
|
||||
*
|
||||
|
@ -1761,12 +1758,12 @@ public final class InputLogic {
|
|||
// word information from textview.
|
||||
return mConnection.getNgramContextFromNthPreviousWord(
|
||||
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 (Constants.CODE_PERIOD == codePointBeforeCursor) {
|
||||
return text.substring(1);
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1877,7 +1873,7 @@ public final class InputLogic {
|
|||
* @param previousSuggestedWords The previously suggested words.
|
||||
* @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 oldSuggestedWords = previousSuggestedWords.isPunctuationSuggestions()
|
||||
? SuggestedWords.getEmptyInstance() : previousSuggestedWords;
|
||||
|
|
|
@ -23,7 +23,6 @@ import android.os.Message;
|
|||
import com.android.inputmethod.compat.LooperCompatUtils;
|
||||
import com.android.inputmethod.latin.InputPointers;
|
||||
import com.android.inputmethod.latin.LatinIME;
|
||||
import com.android.inputmethod.latin.Suggest;
|
||||
import com.android.inputmethod.latin.SuggestedWords;
|
||||
import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
|
||||
|
||||
|
@ -62,7 +61,7 @@ class InputLogicHandler implements Handler.Callback {
|
|||
final OnGetSuggestedWordsCallback callback) {}
|
||||
};
|
||||
|
||||
private InputLogicHandler() {
|
||||
InputLogicHandler() {
|
||||
mNonUIThreadHandler = null;
|
||||
mLatinIME = null;
|
||||
mInputLogic = null;
|
||||
|
@ -134,30 +133,38 @@ class InputLogicHandler implements Handler.Callback {
|
|||
return;
|
||||
}
|
||||
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
|
||||
: SuggestedWords.INPUT_STYLE_UPDATE_BATCH, sequenceNumber,
|
||||
new OnGetSuggestedWordsCallback() {
|
||||
@Override
|
||||
public void onGetSuggestedWords(SuggestedWords suggestedWords) {
|
||||
// We're now inside the callback. This always runs on the Non-UI thread,
|
||||
// no matter what thread updateBatchInput was originally called on.
|
||||
if (suggestedWords.isEmpty()) {
|
||||
// Use old suggestions if we don't have any new ones.
|
||||
// Previous suggestions are found in InputLogic#mSuggestedWords.
|
||||
// Since these are the most recent ones and we just recomputed
|
||||
// new ones to update them, then the previous ones are there.
|
||||
suggestedWords = mInputLogic.mSuggestedWords;
|
||||
}
|
||||
mLatinIME.mHandler.showGesturePreviewAndSuggestionStrip(suggestedWords,
|
||||
isTailBatchInput /* dismissGestureFloatingPreviewText */);
|
||||
if (isTailBatchInput) {
|
||||
mInBatchInput = false;
|
||||
// The following call schedules onEndBatchInputInternal
|
||||
// to be called on the UI thread.
|
||||
mLatinIME.mHandler.showTailBatchInputResult(suggestedWords);
|
||||
}
|
||||
}
|
||||
});
|
||||
: SuggestedWords.INPUT_STYLE_UPDATE_BATCH, sequenceNumber, callback);
|
||||
}
|
||||
}
|
||||
|
||||
void showGestureSuggestionsWithPreviewVisuals(final SuggestedWords suggestedWordsForBatchInput,
|
||||
final boolean isTailBatchInput) {
|
||||
final SuggestedWords suggestedWordsToShowSuggestions;
|
||||
// We're now inside the callback. This always runs on the Non-UI thread,
|
||||
// no matter what thread updateBatchInput was originally called on.
|
||||
if (suggestedWordsForBatchInput.isEmpty()) {
|
||||
// Use old suggestions if we don't have any new ones.
|
||||
// Previous suggestions are found in InputLogic#mSuggestedWords.
|
||||
// Since these are the most recent ones and we just recomputed
|
||||
// new ones to update them, then the previous ones are there.
|
||||
suggestedWordsToShowSuggestions = mInputLogic.mSuggestedWords;
|
||||
} else {
|
||||
suggestedWordsToShowSuggestions = suggestedWordsForBatchInput;
|
||||
}
|
||||
mLatinIME.mHandler.showGesturePreviewAndSuggestionStrip(suggestedWordsToShowSuggestions,
|
||||
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) {
|
||||
return probabilityInfo1;
|
||||
}
|
||||
if (probabilityInfo1.mProbability > probabilityInfo2.mProbability) {
|
||||
return probabilityInfo1;
|
||||
} else {
|
||||
return probabilityInfo2;
|
||||
}
|
||||
return (probabilityInfo1.mProbability > probabilityInfo2.mProbability) ? probabilityInfo1
|
||||
: probabilityInfo2;
|
||||
}
|
||||
|
||||
public ProbabilityInfo(final int probability) {
|
||||
|
@ -67,9 +64,8 @@ public final class ProbabilityInfo {
|
|||
public int hashCode() {
|
||||
if (hasHistoricalInfo()) {
|
||||
return Arrays.hashCode(new Object[] { mProbability, mTimestamp, mLevel, mCount });
|
||||
} else {
|
||||
return Arrays.hashCode(new Object[] { mProbability });
|
||||
}
|
||||
return Arrays.hashCode(new Object[] { mProbability });
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.android.inputmethod.latin.makedict;
|
|||
|
||||
import com.android.inputmethod.annotations.UsedForTesting;
|
||||
import com.android.inputmethod.latin.BinaryDictionary;
|
||||
import com.android.inputmethod.latin.Dictionary;
|
||||
import com.android.inputmethod.latin.NgramContext;
|
||||
import com.android.inputmethod.latin.NgramContext.WordInfo;
|
||||
import com.android.inputmethod.latin.utils.CombinedFormatUtils;
|
||||
|
@ -61,10 +62,8 @@ public final class WordProperty implements Comparable<WordProperty> {
|
|||
} else {
|
||||
mNgrams = new ArrayList<>();
|
||||
final NgramContext ngramContext = new NgramContext(new WordInfo(mWord));
|
||||
if (bigrams != null) {
|
||||
for (final WeightedString bigramTarget : bigrams) {
|
||||
mNgrams.add(new NgramProperty(bigramTarget, ngramContext));
|
||||
}
|
||||
for (final WeightedString bigramTarget : bigrams) {
|
||||
mNgrams.add(new NgramProperty(bigramTarget, ngramContext));
|
||||
}
|
||||
}
|
||||
mIsBeginningOfSentence = false;
|
||||
|
@ -104,7 +103,8 @@ public final class WordProperty implements Comparable<WordProperty> {
|
|||
|
||||
final int relatedNgramCount = ngramTargets.size();
|
||||
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);
|
||||
for (int i = 0; i < relatedNgramCount; i++) {
|
||||
final String ngramTargetString =
|
||||
|
@ -202,7 +202,7 @@ public final class WordProperty implements Comparable<WordProperty> {
|
|||
|
||||
@UsedForTesting
|
||||
public boolean isValid() {
|
||||
return getProbability() != BinaryDictionary.NOT_A_PROBABILITY;
|
||||
return getProbability() != Dictionary.NOT_A_PROBABILITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -85,12 +85,11 @@ public class BlockingHttpClient {
|
|||
throw new AuthException(mConnection.getResponseMessage());
|
||||
}
|
||||
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 {
|
||||
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_NOT_IN_DICTS = Dictionary.NOT_A_PROBABILITY;
|
||||
|
||||
/** The locale for this dictionary. */
|
||||
public final Locale mLocale;
|
||||
|
||||
protected DecayingExpandableBinaryDictionaryBase(final Context context,
|
||||
final String dictName, final Locale locale, final String dictionaryType,
|
||||
final File dictFile) {
|
||||
super(context, dictName, locale, dictionaryType, dictFile);
|
||||
mLocale = locale;
|
||||
if (mLocale != null && mLocale.toString().length() > 1) {
|
||||
reloadDictionaryIfRequired();
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package com.android.inputmethod.latin.personalization;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.inputmethod.annotations.UsedForTesting;
|
||||
import com.android.inputmethod.latin.Constants;
|
||||
|
@ -35,7 +34,6 @@ import java.util.Locale;
|
|||
*/
|
||||
public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase {
|
||||
/* package */ static final String NAME = UserHistoryDictionary.class.getSimpleName();
|
||||
private final static int SUPPORTED_NGRAM = 2; // TODO: 3
|
||||
|
||||
// TODO: Make this constructor private
|
||||
/* package */ UserHistoryDictionary(final Context context, final Locale locale) {
|
||||
|
|
|
@ -259,6 +259,7 @@ final class CustomInputStylePreference extends DialogPreference
|
|||
mSubtype = (InputMethodSubtype)source.readParcelable(null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("hiding")
|
||||
public static final Parcelable.Creator<SavedState> CREATOR =
|
||||
new Parcelable.Creator<SavedState>() {
|
||||
@Override
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package com.android.inputmethod.latin.settings;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.inputmethod.latin.R;
|
||||
|
|
|
@ -20,8 +20,6 @@ import android.os.Bundle;
|
|||
|
||||
import com.android.inputmethod.latin.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* "Multilingual options" settings sub screen.
|
||||
*
|
||||
|
|
|
@ -43,9 +43,7 @@ public class RadioButtonPreference extends Preference {
|
|||
private final View.OnClickListener mClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
if (mListener != null) {
|
||||
mListener.onRadioButtonClicked(RadioButtonPreference.this);
|
||||
}
|
||||
callListenerOnRadioButtonClicked();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -67,6 +65,12 @@ public class RadioButtonPreference extends Preference {
|
|||
mListener = listener;
|
||||
}
|
||||
|
||||
void callListenerOnRadioButtonClicked() {
|
||||
if (mListener != null) {
|
||||
mListener.onRadioButtonClicked(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindView(final View view) {
|
||||
super.onBindView(view);
|
||||
|
|
|
@ -273,9 +273,8 @@ public class SettingsValues {
|
|||
final RichInputMethodManager imm = RichInputMethodManager.getInstance();
|
||||
if (mIncludesOtherImesInLanguageSwitchList) {
|
||||
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) {
|
||||
|
|
|
@ -50,9 +50,6 @@ import java.util.concurrent.Semaphore;
|
|||
*/
|
||||
public final class AndroidSpellCheckerService extends SpellCheckerService
|
||||
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";
|
||||
|
||||
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
|
||||
if (DBG) {
|
||||
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;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.view.textservice.SentenceSuggestionsInfo;
|
||||
import android.view.textservice.SuggestionsInfo;
|
||||
import android.view.textservice.TextInfo;
|
||||
|
@ -76,19 +78,19 @@ public class SentenceLevelAdapter {
|
|||
private static class WordIterator {
|
||||
private final SpacingAndPunctuations mSpacingAndPunctuations;
|
||||
public WordIterator(final Resources res, final Locale locale) {
|
||||
final RunInLocale<SpacingAndPunctuations> job
|
||||
= new RunInLocale<SpacingAndPunctuations>() {
|
||||
final RunInLocale<SpacingAndPunctuations> job =
|
||||
new RunInLocale<SpacingAndPunctuations>() {
|
||||
@Override
|
||||
protected SpacingAndPunctuations job(final Resources res) {
|
||||
return new SpacingAndPunctuations(res);
|
||||
protected SpacingAndPunctuations job(final Resources r) {
|
||||
return new SpacingAndPunctuations(r);
|
||||
}
|
||||
};
|
||||
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();
|
||||
index = index < 0 ? 0 : Character.offsetByCodePoints(sequence, index, 1);
|
||||
int index = fromIndex < 0 ? 0 : Character.offsetByCodePoints(sequence, fromIndex, 1);
|
||||
while (index < length) {
|
||||
final int codePoint = Character.codePointAt(sequence, index);
|
||||
if (mSpacingAndPunctuations.isWordSeparator(codePoint)) {
|
||||
|
@ -111,12 +113,12 @@ public class SentenceLevelAdapter {
|
|||
return index;
|
||||
}
|
||||
|
||||
public int getBeginningOfNextWord(final CharSequence sequence, int index) {
|
||||
public int getBeginningOfNextWord(final CharSequence sequence, final int fromIndex) {
|
||||
final int length = sequence.length();
|
||||
if (index >= length) {
|
||||
if (fromIndex >= length) {
|
||||
return -1;
|
||||
}
|
||||
index = index < 0 ? 0 : Character.offsetByCodePoints(sequence, index, 1);
|
||||
int index = fromIndex < 0 ? 0 : Character.offsetByCodePoints(sequence, fromIndex, 1);
|
||||
while (index < length) {
|
||||
final int codePoint = Character.codePointAt(sequence, index);
|
||||
if (!mSpacingAndPunctuations.isWordSeparator(codePoint)) {
|
||||
|
@ -140,7 +142,7 @@ public class SentenceLevelAdapter {
|
|||
final int cookie = originalTextInfo.getCookie();
|
||||
final int start = -1;
|
||||
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 wordEnd = wordIterator.getEndOfWord(originalText, wordStart);
|
||||
while (wordStart <= end && wordEnd != -1 && wordStart != -1) {
|
||||
|
@ -158,6 +160,7 @@ public class SentenceLevelAdapter {
|
|||
return new SentenceTextInfoParams(originalTextInfo, wordItems);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
public static SentenceSuggestionsInfo reconstructSuggestions(
|
||||
SentenceTextInfoParams originalTextInfoParams, SuggestionsInfo[] results) {
|
||||
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.SuggestedWords;
|
||||
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.SettingsValues;
|
||||
import com.android.inputmethod.latin.utils.AutoCorrectionUtils;
|
||||
import com.android.inputmethod.latin.utils.ResourceUtils;
|
||||
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
||||
import com.android.inputmethod.latin.utils.ViewLayoutUtils;
|
||||
|
@ -380,6 +378,7 @@ final class SuggestionStripLayoutHelper {
|
|||
|
||||
final int countInStrip = mSuggestionsCountInStrip;
|
||||
mMoreSuggestionsAvailable = (wordCountToShow > countInStrip);
|
||||
@SuppressWarnings("unused")
|
||||
int x = 0;
|
||||
for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) {
|
||||
if (positionInStrip != 0) {
|
||||
|
|
|
@ -177,12 +177,11 @@ public class UserDictionarySettings extends ListFragment {
|
|||
return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION,
|
||||
QUERY_SELECTION_ALL_LOCALES, null,
|
||||
"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() {
|
||||
|
|
|
@ -59,11 +59,7 @@ public class AsyncResultHolder<E> {
|
|||
*/
|
||||
public E get(final E defaultValue, final long timeOut) {
|
||||
try {
|
||||
if (mLatch.await(timeOut, TimeUnit.MILLISECONDS)) {
|
||||
return mResult;
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
return mLatch.await(timeOut, TimeUnit.MILLISECONDS) ? mResult : defaultValue;
|
||||
} catch (InterruptedException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import com.android.inputmethod.latin.define.DebugFlags;
|
|||
public final class AutoCorrectionUtils {
|
||||
private static final boolean DBG = DebugFlags.DEBUG_ENABLED;
|
||||
private static final String TAG = AutoCorrectionUtils.class.getSimpleName();
|
||||
private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4;
|
||||
|
||||
private AutoCorrectionUtils() {
|
||||
// Purely static class: can't instantiate.
|
||||
|
|
|
@ -18,9 +18,6 @@ package com.android.inputmethod.latin.utils;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public final class CollectionUtils {
|
||||
private CollectionUtils() {
|
||||
|
@ -47,7 +44,7 @@ public final class CollectionUtils {
|
|||
* @param c Collection to test.
|
||||
* @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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import android.inputmethodservice.InputMethodService;
|
|||
import android.os.Build;
|
||||
import android.text.Layout;
|
||||
import android.text.Spannable;
|
||||
import android.text.Spanned;
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
import android.view.inputmethod.CursorAnchorInfo;
|
||||
|
@ -149,7 +150,7 @@ public final class CursorAnchorInfoUtils {
|
|||
final Object[] spans = spannable.getSpans(0, text.length(), Object.class);
|
||||
for (Object span : spans) {
|
||||
final int spanFlag = spannable.getSpanFlags(span);
|
||||
if ((spanFlag & Spannable.SPAN_COMPOSING) != 0) {
|
||||
if ((spanFlag & Spanned.SPAN_COMPOSING) != 0) {
|
||||
composingTextStart = Math.min(composingTextStart,
|
||||
spannable.getSpanStart(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
|
||||
// because they have passed the filtering in the past.
|
||||
return false;
|
||||
} else {
|
||||
return mDistracterFilter.isDistracterToWordsInDictionaries(
|
||||
ngramContext, testedWord, locale);
|
||||
}
|
||||
return mDistracterFilter.isDistracterToWordsInDictionaries(
|
||||
ngramContext, testedWord, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -27,7 +27,7 @@ import java.util.concurrent.ThreadFactory;
|
|||
* Utilities to manage executors.
|
||||
*/
|
||||
public class ExecutorUtils {
|
||||
private static final ConcurrentHashMap<String, ExecutorService> sExecutorMap =
|
||||
static final ConcurrentHashMap<String, ExecutorService> sExecutorMap =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
private static class ThreadFactoryWithId implements ThreadFactory {
|
||||
|
@ -49,7 +49,7 @@ public class ExecutorUtils {
|
|||
public static ExecutorService getExecutor(final String id) {
|
||||
ExecutorService executor = sExecutorMap.get(id);
|
||||
if (executor == null) {
|
||||
synchronized(sExecutorMap) {
|
||||
synchronized (sExecutorMap) {
|
||||
executor = sExecutorMap.get(id);
|
||||
if (executor == null) {
|
||||
executor = Executors.newSingleThreadExecutor(new ThreadFactoryWithId(id));
|
||||
|
@ -65,7 +65,7 @@ public class ExecutorUtils {
|
|||
*/
|
||||
@UsedForTesting
|
||||
public static void shutdownAllExecutors() {
|
||||
synchronized(sExecutorMap) {
|
||||
synchronized (sExecutorMap) {
|
||||
for (final ExecutorService executor : sExecutorMap.values()) {
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
|
|
|
@ -20,7 +20,6 @@ import android.util.Log;
|
|||
|
||||
import com.android.inputmethod.annotations.UsedForTesting;
|
||||
import com.android.inputmethod.latin.Dictionary;
|
||||
import com.android.inputmethod.latin.DictionaryFacilitator;
|
||||
import com.android.inputmethod.latin.NgramContext;
|
||||
import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
|
||||
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 (focusedWordIndex < 0) {
|
||||
prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE;
|
||||
prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO;
|
||||
break;
|
||||
}
|
||||
final String focusedWord = w[focusedWordIndex];
|
||||
// If the word is, the context is beginning-of-sentence.
|
||||
final int length = focusedWord.length();
|
||||
if (length <= 0) {
|
||||
prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE;
|
||||
prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO;
|
||||
break;
|
||||
}
|
||||
// If ends in a sentence separator, the context is beginning-of-sentence.
|
||||
final char lastChar = focusedWord.charAt(length - 1);
|
||||
if (spacingAndPunctuations.isSentenceSeparator(lastChar)) {
|
||||
prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE;
|
||||
prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO;
|
||||
break;
|
||||
}
|
||||
// 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
|
||||
// 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.
|
||||
fl &= ~Spannable.SPAN_PARAGRAPH;
|
||||
fl &= ~Spanned.SPAN_PARAGRAPH;
|
||||
|
||||
int st = source.getSpanStart(spans[i]);
|
||||
int en = source.getSpanEnd(spans[i]);
|
||||
|
|
|
@ -39,7 +39,7 @@ import java.util.Locale;
|
|||
*/
|
||||
// TODO: consolidate this into RichInputMethodSubtype
|
||||
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.
|
||||
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
|
||||
&& subtype.containsExtraValueKey(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) {
|
||||
|
|
|
@ -66,8 +66,7 @@ public final class SuggestionResults extends TreeSet<SuggestedWordInfo> {
|
|||
return super.addAll(e);
|
||||
}
|
||||
|
||||
private static final class SuggestedWordInfoComparator
|
||||
implements Comparator<SuggestedWordInfo> {
|
||||
static final class SuggestedWordInfoComparator implements Comparator<SuggestedWordInfo> {
|
||||
// This comparator ranks the word info with the higher frequency first. That's because
|
||||
// that's the order we want our elements in.
|
||||
@Override
|
||||
|
|
|
@ -20,7 +20,6 @@ import android.graphics.Typeface;
|
|||
import android.os.Build;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.StyleSpan;
|
||||
|
@ -72,141 +71,141 @@ public class LocaleSpanCompatUtilsTests extends AndroidTestCase {
|
|||
final SpannableString text = new SpannableString("0123456789");
|
||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE);
|
||||
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.
|
||||
{
|
||||
final SpannableString text = new SpannableString("0123456789");
|
||||
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);
|
||||
assertSpanCount(2, text);
|
||||
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.
|
||||
{
|
||||
final SpannableString text = new SpannableString("0123456789");
|
||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 3,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 5, Locale.JAPANESE);
|
||||
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.
|
||||
{
|
||||
final SpannableString text = new SpannableString("0123456789");
|
||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 4,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 5, Locale.JAPANESE);
|
||||
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.
|
||||
{
|
||||
final SpannableString text = new SpannableString("0123456789");
|
||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 4,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 5, 6,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 2, 8, Locale.JAPANESE);
|
||||
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.
|
||||
{
|
||||
final SpannableString text = new SpannableString("0123456789");
|
||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 3,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 5, 6,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 8, 9, Locale.JAPANESE);
|
||||
assertSpanCount(3, text);
|
||||
assertLocaleSpan(text, 0, 1, 3, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
assertLocaleSpan(text, 1, 5, 6, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
assertLocaleSpan(text, 2, 8, 9, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
assertLocaleSpan(text, 0, 1, 3, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
assertLocaleSpan(text, 1, 5, 6, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
assertLocaleSpan(text, 2, 8, 9, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
|
||||
// Test if existing span flags are preserved during merge.
|
||||
{
|
||||
final SpannableString text = new SpannableString("0123456789");
|
||||
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);
|
||||
assertSpanCount(1, text);
|
||||
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).
|
||||
{
|
||||
final SpannableString text = new SpannableString("0123456789");
|
||||
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);
|
||||
assertSpanCount(1, text);
|
||||
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).
|
||||
{
|
||||
final SpannableString text = new SpannableString("0123456789");
|
||||
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);
|
||||
assertSpanCount(1, text);
|
||||
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.
|
||||
{
|
||||
final SpannableString text = new SpannableString("0123456789");
|
||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 5,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 7, Locale.JAPANESE);
|
||||
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)
|
||||
{
|
||||
final SpannableString text = new SpannableString("0123456789");
|
||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 5, 6, Locale.JAPANESE);
|
||||
assertSpanCount(3, text);
|
||||
assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
assertLocaleSpan(text, 1, 6, 7, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
assertLocaleSpan(text, 2, 5, 6, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
assertLocaleSpan(text, 1, 6, 7, Locale.ENGLISH, Spanned.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)
|
||||
{
|
||||
final SpannableString text = new SpannableString("0123456789");
|
||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 2, 5, Locale.JAPANESE);
|
||||
assertSpanCount(2, text);
|
||||
assertLocaleSpan(text, 0, 5, 7, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
assertLocaleSpan(text, 1, 2, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
assertLocaleSpan(text, 0, 5, 7, Locale.ENGLISH, Spanned.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)
|
||||
{
|
||||
final SpannableString text = new SpannableString("0123456789");
|
||||
text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
LocaleSpanCompatUtils.updateLocaleSpan(text, 5, 8, Locale.JAPANESE);
|
||||
assertSpanCount(2, text);
|
||||
assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
assertLocaleSpan(text, 1, 5, 8, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spanned.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);
|
||||
}
|
||||
|
||||
@SuppressWarnings("static-method")
|
||||
public void testEmptyEntry() {
|
||||
assertInsertAdditionalMoreKeys("null more keys and null additons",
|
||||
null,
|
||||
|
@ -106,6 +107,7 @@ public final class MoreKeySpecTests extends KeySpecParserTestsBase {
|
|||
new String[] { "a", "A", "b", "B", "c", "d" });
|
||||
}
|
||||
|
||||
@SuppressWarnings("static-method")
|
||||
public void testInsertAdditionalMoreKeys() {
|
||||
// Escaped marker.
|
||||
assertInsertAdditionalMoreKeys("escaped marker",
|
||||
|
@ -306,6 +308,7 @@ public final class MoreKeySpecTests extends KeySpecParserTestsBase {
|
|||
assertArrayEquals(message, expected, actual);
|
||||
}
|
||||
|
||||
@SuppressWarnings("static-method")
|
||||
public void testGetBooleanValue() {
|
||||
assertGetBooleanValue("Has label", HAS_LABEL,
|
||||
new String[] { HAS_LABEL, "a", "b", "c" },
|
||||
|
@ -345,6 +348,7 @@ public final class MoreKeySpecTests extends KeySpecParserTestsBase {
|
|||
assertArrayEquals(message, expected, actual);
|
||||
}
|
||||
|
||||
@SuppressWarnings("static-method")
|
||||
public void testGetIntValue() {
|
||||
assertGetIntValue("Fixed column order 3", FIXED_COLUMN_ORDER, -1,
|
||||
new String[] { FIXED_COLUMN_ORDER + "3", "a", "b", "c" },
|
||||
|
|
|
@ -174,13 +174,12 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
|
|||
if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), formatVersion,
|
||||
LocaleUtils.constructLocaleFromString(TEST_LOCALE), attributeMap)) {
|
||||
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(),
|
||||
0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
|
||||
Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
|
||||
|
@ -683,7 +682,7 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
|
|||
final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
|
||||
|
||||
binaryDictionary.addUnigramEntry("", DUMMY_PROBABILITY, "" /* shortcutTarget */,
|
||||
BinaryDictionary.NOT_A_PROBABILITY /* shortcutProbability */,
|
||||
Dictionary.NOT_A_PROBABILITY /* shortcutProbability */,
|
||||
true /* isBeginningOfSentence */, true /* isNotAWord */,
|
||||
false /* isPossiblyOffensive */, mCurrentTime);
|
||||
final NgramContext beginningOfSentenceContext = NgramContext.BEGINNING_OF_SENTENCE;
|
||||
|
|
|
@ -111,13 +111,12 @@ public class BinaryDictionaryTests extends AndroidTestCase {
|
|||
if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), formatVersion,
|
||||
Locale.ENGLISH, attributeMap)) {
|
||||
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(),
|
||||
0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
|
||||
Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
|
||||
|
@ -211,15 +210,14 @@ public class BinaryDictionaryTests extends AndroidTestCase {
|
|||
|
||||
assertEquals(probability, binaryDictionary.getFrequency("aaa"));
|
||||
assertEquals(updatedProbability, binaryDictionary.getFrequency(validLongWord));
|
||||
assertEquals(BinaryDictionary.NOT_A_PROBABILITY,
|
||||
binaryDictionary.getFrequency(invalidLongWord));
|
||||
assertEquals(Dictionary.NOT_A_PROBABILITY, binaryDictionary.getFrequency(invalidLongWord));
|
||||
assertEquals(updatedProbability, binaryDictionary.getFrequency("abc"));
|
||||
}
|
||||
|
||||
private static void addUnigramWord(final BinaryDictionary binaryDictionary, final String word,
|
||||
final int probability) {
|
||||
binaryDictionary.addUnigramEntry(word, probability, "" /* shortcutTarget */,
|
||||
BinaryDictionary.NOT_A_PROBABILITY /* shortcutProbability */,
|
||||
Dictionary.NOT_A_PROBABILITY /* shortcutProbability */,
|
||||
false /* isBeginningOfSentence */, false /* isNotAWord */,
|
||||
false /* isPossiblyOffensive */,
|
||||
BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
|
||||
|
@ -975,7 +973,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
|
|||
final boolean isPossiblyOffensive = random.nextBoolean();
|
||||
// TODO: Add tests for historical info.
|
||||
binaryDictionary.addUnigramEntry(word, unigramProbability,
|
||||
null /* shortcutTarget */, BinaryDictionary.NOT_A_PROBABILITY,
|
||||
null /* shortcutTarget */, Dictionary.NOT_A_PROBABILITY,
|
||||
false /* isBeginningOfSentence */, isNotAWord, isPossiblyOffensive,
|
||||
BinaryDictionary.NOT_A_VALID_TIMESTAMP);
|
||||
if (binaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
|
||||
|
@ -1264,7 +1262,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
|
|||
WordProperty wordProperty = binaryDictionary.getWordProperty("ddd", false);
|
||||
assertEquals(true, wordProperty.mIsPossiblyOffensive);
|
||||
}
|
||||
|
||||
|
||||
public void testDictMigration() {
|
||||
for (final int formatVersion : DICT_FORMAT_VERSIONS) {
|
||||
testDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, formatVersion);
|
||||
|
|
|
@ -61,7 +61,6 @@ public class BlueUnderlineTests extends InputTestsBase {
|
|||
public void testBlueUnderlineOnBackspace() {
|
||||
final String STRING_TO_TYPE = "tgis";
|
||||
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_END = 3;
|
||||
type(STRING_TO_TYPE);
|
||||
|
|
|
@ -47,7 +47,7 @@ public class DictionaryFacilitatorLruCacheTests extends AndroidTestCase {
|
|||
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);
|
||||
assertNotNull(dictionaryFacilitatorEnUs);
|
||||
assertTrue(dictionaryFacilitatorEnUs.isForLocales(new Locale[] { Locale.US }));
|
||||
|
@ -68,7 +68,7 @@ public class DictionaryFacilitatorLruCacheTests extends AndroidTestCase {
|
|||
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));
|
||||
cache.setUseContactsDictionary(true /* useContactsDictionary */);
|
||||
assertNotNull(cache.get(Locale.US).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
|
||||
|
|
|
@ -25,7 +25,7 @@ import java.util.ArrayList;
|
|||
@LargeTest
|
||||
public class InputLogicTestsDeadKeys extends InputTestsBase {
|
||||
// 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) {
|
||||
final Event event;
|
||||
if (isDead) {
|
||||
|
|
|
@ -80,7 +80,6 @@ import android.util.Pair;
|
|||
@LargeTest
|
||||
// These tests are inactive until the combining code for Myanmar Reordering is sorted out.
|
||||
@Suppress
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class InputLogicTestsReorderingMyanmar extends InputTestsBase {
|
||||
// The tests are formatted as follows.
|
||||
// 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
|
||||
// key press.
|
||||
|
||||
private static final Pair[][] TESTS = {
|
||||
private static final Pair<?, ?>[][] TESTS = {
|
||||
|
||||
// Tests for U+1031 MYANMAR VOWEL SIGN E : ေ
|
||||
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;
|
||||
for (final Pair<int[], String> step : test) {
|
||||
for (final Pair<?, ?> step : test) {
|
||||
++stepNumber;
|
||||
final int[] input = step.first;
|
||||
final String expectedResult = step.second;
|
||||
final int[] input = (int[]) step.first;
|
||||
final String expectedResult = (String) step.second;
|
||||
if (input.length > 1) {
|
||||
mLatinIME.onTextInput(new String(input, 0, input.length));
|
||||
} else {
|
||||
|
@ -226,7 +224,7 @@ public class InputLogicTestsReorderingMyanmar extends InputTestsBase {
|
|||
public void testMyanmarReordering() {
|
||||
int testNumber = 0;
|
||||
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
|
||||
// LatinIME has never seen, and cursor pos 0,0.
|
||||
mEditText.setText("");
|
||||
|
|
|
@ -40,7 +40,6 @@ import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
|
|||
import com.android.inputmethod.event.Event;
|
||||
import com.android.inputmethod.keyboard.Key;
|
||||
import com.android.inputmethod.keyboard.Keyboard;
|
||||
import com.android.inputmethod.latin.Dictionary;
|
||||
import com.android.inputmethod.latin.Dictionary.PhonyDictionary;
|
||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||
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
|
||||
// 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.
|
||||
private final class InterruptRunMessagesException extends RuntimeException {
|
||||
final class InterruptRunMessagesException extends RuntimeException {
|
||||
// Empty class
|
||||
}
|
||||
protected void runMessages() {
|
||||
|
@ -284,7 +283,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
|
|||
} else {
|
||||
final int x = key.getX() + key.getWidth() / 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);
|
||||
// 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);
|
||||
if (key == null) {
|
||||
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) {
|
||||
|
@ -386,7 +384,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
|
|||
false /* isAuxiliary */,
|
||||
false /* overridesImplicitlyEnabledSubtype */,
|
||||
0 /* id */);
|
||||
SubtypeSwitcher.getInstance().forceSubtype(subtype);
|
||||
SubtypeSwitcher.forceSubtype(subtype);
|
||||
mLatinIME.onCurrentInputMethodSubtypeChanged(subtype);
|
||||
runMessages();
|
||||
mKeyboard = mLatinIME.mKeyboardSwitcher.getKeyboard();
|
||||
|
|
|
@ -25,8 +25,8 @@ import android.test.suitebuilder.annotation.SmallTest;
|
|||
public class NgramContextTests extends AndroidTestCase {
|
||||
public void testConstruct() {
|
||||
assertEquals(new NgramContext(new WordInfo("a")), new NgramContext(new WordInfo("a")));
|
||||
assertEquals(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE),
|
||||
new NgramContext(WordInfo.BEGINNING_OF_SENTENCE));
|
||||
assertEquals(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO),
|
||||
new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO));
|
||||
assertEquals(new NgramContext(WordInfo.EMPTY_WORD_INFO),
|
||||
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() {
|
||||
assertFalse(new NgramContext().isBeginningOfSentenceContext());
|
||||
assertTrue(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE)
|
||||
assertTrue(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO)
|
||||
.isBeginningOfSentenceContext());
|
||||
assertTrue(NgramContext.BEGINNING_OF_SENTENCE.isBeginningOfSentenceContext());
|
||||
assertFalse(new NgramContext(new WordInfo("a")).isBeginningOfSentenceContext());
|
||||
assertFalse(new NgramContext(new WordInfo("")).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());
|
||||
assertFalse(new NgramContext(new WordInfo("a"), WordInfo.BEGINNING_OF_SENTENCE)
|
||||
assertFalse(new NgramContext(new WordInfo("a"), WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO)
|
||||
.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());
|
||||
}
|
||||
|
||||
|
@ -56,7 +57,7 @@ public class NgramContextTests extends AndroidTestCase {
|
|||
assertEquals("b", ngramContext_b_a.getNthPrevWord(1));
|
||||
assertEquals("a", ngramContext_b_a.getNthPrevWord(2));
|
||||
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());
|
||||
assertEquals("b", ngramContext_bos_b.getNthPrevWord(2));
|
||||
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;
|
||||
public void setInputConnection(final MockConnection mockConnection) {
|
||||
mMockConnection = mockConnection;
|
||||
|
@ -221,7 +221,6 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
|
|||
mSpacingAndPunctuations, new int[] { Constants.CODE_SPACE });
|
||||
final SpacingAndPunctuations TAB = new SpacingAndPunctuations(
|
||||
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).
|
||||
final String SUPPLEMENTARY_CHAR_STRING = "\uD840\uDC8A";
|
||||
final SpacingAndPunctuations SUPPLEMENTARY_CHAR = new SpacingAndPunctuations(
|
||||
|
|
|
@ -16,14 +16,10 @@
|
|||
|
||||
package com.android.inputmethod.latin;
|
||||
|
||||
import android.os.Build;
|
||||
import android.test.suitebuilder.annotation.LargeTest;
|
||||
import android.text.TextUtils;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
|
||||
import com.android.inputmethod.latin.Constants;
|
||||
import com.android.inputmethod.latin.WordComposer;
|
||||
|
||||
@LargeTest
|
||||
public class ShiftModeTests extends InputTestsBase {
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ public class SuggestedWordsTests extends AndroidTestCase {
|
|||
}
|
||||
|
||||
// Helper for testGetTransformedWordInfo
|
||||
private SuggestedWordInfo transformWordInfo(final String info,
|
||||
private static SuggestedWordInfo transformWordInfo(final String info,
|
||||
final int trailingSingleQuotesCount) {
|
||||
final SuggestedWordInfo suggestedWordInfo = createTypedWordInfo(info);
|
||||
final SuggestedWordInfo returnedWordInfo =
|
||||
|
|
|
@ -117,7 +117,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
|||
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,
|
||||
random);
|
||||
final Set<String> wordSet = new HashSet<>();
|
||||
|
@ -138,7 +138,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
|||
/**
|
||||
* 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) {
|
||||
for (int i = 0; i < number; ++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 SparseArray<List<Integer>> bigrams) {
|
||||
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);
|
||||
// }
|
||||
|
||||
private long timeWritingDictToFile(final File file, final FusionDictionary dict,
|
||||
private static long timeWritingDictToFile(final File file, final FusionDictionary dict,
|
||||
final FormatSpec.FormatOptions formatOptions) {
|
||||
|
||||
long now = -1, diff = -1;
|
||||
|
@ -196,7 +196,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
|||
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 HashMap<String, List<String>> shortcutMap) {
|
||||
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) {
|
||||
String result = " : buffer type = "
|
||||
final String result = " : buffer type = "
|
||||
+ ((bufferType == BinaryDictUtils.USE_BYTE_BUFFER) ? "byte buffer" : "byte array");
|
||||
return result + " : version = " + formatOptions.mVersion;
|
||||
}
|
||||
|
||||
// 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 HashMap<String, List<String>> shortcutMap, final int bufferType) {
|
||||
long now, diff = -1;
|
||||
|
@ -385,7 +385,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
|||
|
||||
// Tests for readUnigramsAndBigramsBinary
|
||||
|
||||
private void checkWordMap(final List<String> expectedWords,
|
||||
private static void checkWordMap(final List<String> expectedWords,
|
||||
final SparseArray<List<Integer>> expectedBigrams,
|
||||
final TreeMap<Integer, String> resultWords,
|
||||
final TreeMap<Integer, Integer> resultFrequencies,
|
||||
|
@ -434,9 +434,9 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
|||
assertEquals(actBigrams, expBigrams);
|
||||
}
|
||||
|
||||
private long timeAndCheckReadUnigramsAndBigramsBinary(final File file, final List<String> words,
|
||||
final SparseArray<List<Integer>> bigrams, final int bufferType,
|
||||
final boolean checkProbability) {
|
||||
private static long timeAndCheckReadUnigramsAndBigramsBinary(final File file,
|
||||
final List<String> words, final SparseArray<List<Integer>> bigrams,
|
||||
final int bufferType, final boolean checkProbability) {
|
||||
final TreeMap<Integer, String> resultWords = new TreeMap<>();
|
||||
final TreeMap<Integer, ArrayList<PendingAttribute>> resultBigrams = new TreeMap<>();
|
||||
final TreeMap<Integer, Integer> resultFreqs = new TreeMap<>();
|
||||
|
@ -519,7 +519,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
|||
}
|
||||
|
||||
// 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);
|
||||
|
||||
DictionaryHeader fileHeader = null;
|
||||
|
@ -535,7 +535,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
|
|||
address).mWord;
|
||||
}
|
||||
|
||||
private long checkGetTerminalPosition(final DictDecoder dictDecoder, final String word,
|
||||
private static long checkGetTerminalPosition(final DictDecoder dictDecoder, final String word,
|
||||
final boolean contained) {
|
||||
long diff = -1;
|
||||
int position = -1;
|
||||
|
|
|
@ -113,15 +113,16 @@ public final class BinaryDictDecoderUtils {
|
|||
/**
|
||||
* 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) {
|
||||
int codePoint = character;
|
||||
if (codePointToOneByteCodeMap != null) {
|
||||
if (codePointToOneByteCodeMap.containsKey(character)) {
|
||||
character = codePointToOneByteCodeMap.get(character);
|
||||
codePoint = codePointToOneByteCodeMap.get(character);
|
||||
}
|
||||
}
|
||||
return character >= FormatSpec.MINIMAL_ONE_BYTE_CHARACTER_VALUE
|
||||
&& character <= FormatSpec.MAXIMAL_ONE_BYTE_CHARACTER_VALUE;
|
||||
return codePoint >= FormatSpec.MINIMAL_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.
|
||||
* @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) {
|
||||
int index = fromIndex;
|
||||
for (int codePoint : codePoints) {
|
||||
if (codePointToOneByteCodeMap != null) {
|
||||
if (codePointToOneByteCodeMap.containsKey(codePoint)) {
|
||||
|
@ -293,10 +295,9 @@ public final class BinaryDictDecoderUtils {
|
|||
final int msb = dictBuffer.readUnsignedByte();
|
||||
if (FormatSpec.MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT >= 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) {
|
||||
int position = fromPosition;
|
||||
switch(size) {
|
||||
case 4:
|
||||
buffer[position++] = (byte) ((value >> 24) & 0xFF);
|
||||
|
@ -324,11 +325,9 @@ public class BinaryDictEncoderUtils {
|
|||
return targetNodeArray.mCachedAddressAfterUpdate
|
||||
- (currentNodeArray.mCachedAddressAfterUpdate
|
||||
+ 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
|
||||
+ offsetFromStartOfCurrentNodeArray;
|
||||
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.
|
||||
* @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) {
|
||||
int index = fromIndex;
|
||||
switch (getByteSize(position)) {
|
||||
case 1:
|
||||
buffer[index++] = (byte)position;
|
||||
|
@ -623,7 +622,7 @@ public class BinaryDictEncoderUtils {
|
|||
* @return the flags
|
||||
*/
|
||||
/* 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)
|
||||
+ (offset < 0 ? FormatSpec.FLAG_BIGRAM_ATTR_OFFSET_NEGATIVE : 0);
|
||||
switch (getByteSize(offset)) {
|
||||
|
@ -639,13 +638,16 @@ public class BinaryDictEncoderUtils {
|
|||
default:
|
||||
throw new RuntimeException("Strange offset size");
|
||||
}
|
||||
final int frequency;
|
||||
if (unigramFrequency > bigramFrequency) {
|
||||
MakedictLog.e("Unigram freq is superior to bigram freq for \"" + word
|
||||
+ "\". Bigram freq is " + bigramFrequency + ", unigram freq for "
|
||||
+ word + " is " + unigramFrequency);
|
||||
bigramFrequency = unigramFrequency;
|
||||
frequency = unigramFrequency;
|
||||
} else {
|
||||
frequency = bigramFrequency;
|
||||
}
|
||||
bigramFlags += getBigramFrequencyDiff(unigramFrequency, bigramFrequency)
|
||||
bigramFlags += getBigramFrequencyDiff(unigramFrequency, frequency)
|
||||
& FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY;
|
||||
return bigramFlags;
|
||||
}
|
||||
|
@ -722,7 +724,6 @@ public class BinaryDictEncoderUtils {
|
|||
* @param ptNodeArray the node array to write.
|
||||
* @param codePointToOneByteCodeMap the map to convert the code points.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
/* package */ static void writePlacedPtNodeArray(final FusionDictionary dict,
|
||||
final DictEncoder dictEncoder, final PtNodeArray ptNodeArray,
|
||||
final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
|
||||
|
|
|
@ -206,11 +206,7 @@ public final class BinaryDictIOUtils {
|
|||
if (same) {
|
||||
// found the PtNode matches the word.
|
||||
if (wordPos + currentInfo.mCharacters.length == wordLen) {
|
||||
if (!currentInfo.isTerminal()) {
|
||||
return FormatSpec.NOT_VALID_WORD;
|
||||
} else {
|
||||
return ptNodePos;
|
||||
}
|
||||
return currentInfo.isTerminal() ? ptNodePos : FormatSpec.NOT_VALID_WORD;
|
||||
}
|
||||
wordPos += currentInfo.mCharacters.length;
|
||||
if (currentInfo.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS) {
|
||||
|
|
|
@ -142,11 +142,7 @@ public final class FusionDictionary implements Iterable<WordProperty> {
|
|||
}
|
||||
|
||||
public int getProbability() {
|
||||
if (isTerminal()) {
|
||||
return mProbabilityInfo.mProbability;
|
||||
} else {
|
||||
return NOT_A_TERMINAL;
|
||||
}
|
||||
return isTerminal() ? mProbabilityInfo.mProbability : NOT_A_TERMINAL;
|
||||
}
|
||||
|
||||
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
|
||||
* 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> bigrams,
|
||||
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.
|
||||
* 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;
|
||||
int lastValue = -1;
|
||||
for (int i = 0; i < stack.size(); ++i) {
|
||||
int currentValue = stack.get(i).mChars[0];
|
||||
if (currentValue <= lastValue)
|
||||
if (currentValue <= lastValue) {
|
||||
throw new RuntimeException("Invalid stack");
|
||||
else
|
||||
lastValue = currentValue;
|
||||
}
|
||||
lastValue = currentValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -521,14 +517,14 @@ public final class FusionDictionary implements Iterable<WordProperty> {
|
|||
* is ignored.
|
||||
* 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
|
||||
public int compare(PtNode p1, PtNode p2) {
|
||||
if (p1.mChars[0] == p2.mChars[0]) return 0;
|
||||
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.
|
||||
|
@ -559,7 +555,8 @@ public final class FusionDictionary implements Iterable<WordProperty> {
|
|||
/**
|
||||
* 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;
|
||||
final StringBuilder checker = DBG ? new StringBuilder() : null;
|
||||
final int[] codePoints = getCodePoints(string);
|
||||
|
|
|
@ -36,17 +36,17 @@ public class Ver2DictDecoder extends AbstractDictDecoder {
|
|||
/**
|
||||
* A utility class for reading a PtNode.
|
||||
*/
|
||||
protected static class PtNodeReader {
|
||||
private static ProbabilityInfo readProbabilityInfo(final DictBuffer dictBuffer) {
|
||||
static class PtNodeReader {
|
||||
static ProbabilityInfo readProbabilityInfo(final DictBuffer dictBuffer) {
|
||||
// Ver2 dicts don't contain historical information.
|
||||
return new ProbabilityInfo(dictBuffer.readUnsignedByte());
|
||||
}
|
||||
|
||||
protected static int readPtNodeOptionFlags(final DictBuffer dictBuffer) {
|
||||
static int readPtNodeOptionFlags(final DictBuffer dictBuffer) {
|
||||
return dictBuffer.readUnsignedByte();
|
||||
}
|
||||
|
||||
protected static int readChildrenAddress(final DictBuffer dictBuffer,
|
||||
static int readChildrenAddress(final DictBuffer dictBuffer,
|
||||
final int ptNodeFlags) {
|
||||
switch (ptNodeFlags & FormatSpec.MASK_CHILDREN_ADDRESS_TYPE) {
|
||||
case FormatSpec.FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE:
|
||||
|
@ -62,7 +62,7 @@ public class Ver2DictDecoder extends AbstractDictDecoder {
|
|||
}
|
||||
|
||||
// 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 int pointerBefore = dictBuffer.position();
|
||||
dictBuffer.readUnsignedShort(); // skip the size
|
||||
|
@ -76,7 +76,7 @@ public class Ver2DictDecoder extends AbstractDictDecoder {
|
|||
return dictBuffer.position() - pointerBefore;
|
||||
}
|
||||
|
||||
protected static int readBigramAddresses(final DictBuffer dictBuffer,
|
||||
static int readBigramAddresses(final DictBuffer dictBuffer,
|
||||
final ArrayList<PendingAttribute> bigrams, final int baseAddress) {
|
||||
int readLength = 0;
|
||||
int bigramCount = 0;
|
||||
|
|
|
@ -27,14 +27,12 @@ import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
|
|||
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.LargeTest;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Unit tests for Ver2DictEncoder
|
||||
*/
|
||||
@LargeTest
|
||||
public class Ver2DictEncoderTests extends AndroidTestCase {
|
||||
private static final String TAG = Ver2DictEncoderTests.class.getSimpleName();
|
||||
private static final int UNIGRAM_FREQ = 10;
|
||||
|
||||
public void testCodePointTable() {
|
||||
|
@ -75,7 +73,7 @@ public class Ver2DictEncoderTests extends AndroidTestCase {
|
|||
/**
|
||||
* 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) {
|
||||
for (final String word : words) {
|
||||
final ArrayList<WeightedString> shortcuts = new ArrayList<>();
|
||||
|
|
|
@ -128,7 +128,7 @@ public class BlockingHttpClientTests extends AndroidTestCase {
|
|||
assertTrue("ResponseProcessor was not invoked", processor.mInvoked);
|
||||
}
|
||||
|
||||
private static class FakeErrorResponseProcessor implements ResponseProcessor<Void> {
|
||||
static class FakeErrorResponseProcessor implements ResponseProcessor<Void> {
|
||||
@Override
|
||||
public Void onSuccess(InputStream response) {
|
||||
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 a new issue