From 73779f7631d41f16f89c62cae09a1b27d8189dc3 Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Wed, 19 Sep 2012 18:00:32 +0900 Subject: Make readUnigramsAndBigramsBinary read linked-list nodes. Change-Id: I07ae036b0b06e71d7a18f2bf11e4692cd4213568 --- .../inputmethod/latin/makedict/BinaryDictIOUtils.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 7a1b9dcb7..406071071 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -92,7 +92,18 @@ public class BinaryDictIOUtils { } if (p.mPosition == p.mNumOfCharGroup) { - stack.pop(); + if (formatOptions.mHasLinkedListNode) { + final int forwardLinkAddress = buffer.readUnsignedInt24(); + if (forwardLinkAddress != FormatSpec.NO_FORWARD_LINK_ADDRESS) { + // the node has a forward link. + p.mNumOfCharGroup = Position.NOT_READ_GROUPCOUNT; + p.mAddress = forwardLinkAddress; + } else { + stack.pop(); + } + } else { + stack.pop(); + } } else { // the node has more groups. p.mAddress = buffer.position(); -- cgit v1.2.3-83-g751a From 66597f5e5f3249f418665c1990fb539d2f5565d5 Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Thu, 20 Sep 2012 14:27:33 +0900 Subject: Add deleteWord. bug: 6669677 Change-Id: I1a5b90ee05e5cffd74a5c140384a3e37c79e7e70 --- .../latin/makedict/BinaryDictIOUtils.java | 22 +++++++++++++ .../latin/makedict/BinaryDictInputOutput.java | 2 +- .../latin/makedict/BinaryDictIOTests.java | 37 +++++++++++++++++++++- 3 files changed, 59 insertions(+), 2 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 406071071..397532933 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -201,4 +201,26 @@ public class BinaryDictIOUtils { } return FormatSpec.NOT_VALID_WORD; } + + /** + * Delete the word from the binary file. + * + * @param buffer the buffer to write. + * @param word the word we delete + * @throws IOException + * @throws UnsupportedFormatException + */ + public static void deleteWord(final FusionDictionaryBufferInterface buffer, + final String word) throws IOException, UnsupportedFormatException { + buffer.position(0); + final FileHeader header = BinaryDictInputOutput.readHeader(buffer); + final int wordPosition = getTerminalPosition(buffer, word); + if (wordPosition == FormatSpec.NOT_VALID_WORD) return; + + buffer.position(wordPosition); + final int flags = buffer.readUnsignedByte(); + final int newFlags = flags ^ FormatSpec.FLAG_IS_TERMINAL; + buffer.position(wordPosition); + buffer.put((byte)newFlags); + } } diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 1d3e94bb7..7b8dc5cc5 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -392,7 +392,7 @@ public class BinaryDictInputOutput { /** * Helper method to check whether the CharGroup has a parent address. */ - private static boolean hasParentAddress(final FormatOptions options) { + public static boolean hasParentAddress(final FormatOptions options) { return options.mVersion >= FormatSpec.FIRST_VERSION_WITH_PARENT_ADDRESS && options.mHasParentAddress; } diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java index 24776d536..539021f24 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java +++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java @@ -25,6 +25,7 @@ import com.android.inputmethod.latin.makedict.FusionDictionary.Node; import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; import android.test.AndroidTestCase; +import android.test.MoreAsserts; import android.util.Log; import android.util.SparseArray; @@ -517,7 +518,7 @@ public class BinaryDictIOTests extends AndroidTestCase { public void testGetTerminalPosition() { File file = null; try { - file = File.createTempFile("runReadUnigrams", ".dict"); + file = File.createTempFile("testGetTerminalPosition", ".dict"); } catch (IOException e) { // do nothing } @@ -564,4 +565,38 @@ public class BinaryDictIOTests extends AndroidTestCase { runGetTerminalPosition(buffer, word, i, false); } } + + public void testDeleteWord() { + File file = null; + try { + file = File.createTempFile("testGetTerminalPosition", ".dict"); + } catch (IOException e) { + // do nothing + } + assertNotNull(file); + + final FusionDictionary dict = new FusionDictionary(new Node(), + new FusionDictionary.DictionaryOptions( + new HashMap(), false, false)); + addUnigrams(sWords.size(), dict, sWords, null /* shortcutMap */); + timeWritingDictToFile(file, dict, VERSION3_WITH_LINKEDLIST_NODE); + + final FusionDictionaryBufferInterface buffer = getBuffer(file, USE_BYTE_ARRAY); + + try { + MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD, + BinaryDictIOUtils.getTerminalPosition(buffer, sWords.get(0))); + BinaryDictIOUtils.deleteWord(buffer, sWords.get(0)); + assertEquals(FormatSpec.NOT_VALID_WORD, + BinaryDictIOUtils.getTerminalPosition(buffer, sWords.get(0))); + + MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD, + BinaryDictIOUtils.getTerminalPosition(buffer, sWords.get(5))); + BinaryDictIOUtils.deleteWord(buffer, sWords.get(5)); + assertEquals(FormatSpec.NOT_VALID_WORD, + BinaryDictIOUtils.getTerminalPosition(buffer, sWords.get(5))); + } catch (IOException e) { + } catch (UnsupportedFormatException e) { + } + } } -- cgit v1.2.3-83-g751a From 8ae8c761493867be7364806cdc4d7103a46dc181 Mon Sep 17 00:00:00 2001 From: Satoshi Kataoka Date: Fri, 21 Sep 2012 15:09:47 +0900 Subject: Cleanup settings bug: 7200189 Change-Id: Ibfd9254670cde5f4b2b693cc9334ee2845bede59 --- java/res/xml/prefs.xml | 10 +++--- java/res/xml/prefs_for_debug.xml | 6 ++++ .../android/inputmethod/latin/DebugSettings.java | 11 ++++++ .../com/android/inputmethod/latin/Settings.java | 41 +++++++--------------- .../android/inputmethod/latin/SettingsValues.java | 2 +- 5 files changed, 35 insertions(+), 35 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml index 3e83fc0fc..478dc0f80 100644 --- a/java/res/xml/prefs.xml +++ b/java/res/xml/prefs.xml @@ -92,11 +92,6 @@ android:summary="@string/gesture_input_summary" android:persistent="true" android:defaultValue="true" /> - + diff --git a/java/res/xml/prefs_for_debug.xml b/java/res/xml/prefs_for_debug.xml index b926ed065..605a02f07 100644 --- a/java/res/xml/prefs_for_debug.xml +++ b/java/res/xml/prefs_for_debug.xml @@ -48,4 +48,10 @@ android:persistent="true" android:defaultValue="false" /> + + diff --git a/java/src/com/android/inputmethod/latin/DebugSettings.java b/java/src/com/android/inputmethod/latin/DebugSettings.java index af7649863..1ea14dad5 100644 --- a/java/src/com/android/inputmethod/latin/DebugSettings.java +++ b/java/src/com/android/inputmethod/latin/DebugSettings.java @@ -23,10 +23,12 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.os.Process; import android.preference.CheckBoxPreference; +import android.preference.Preference; import android.preference.PreferenceFragment; import android.util.Log; import com.android.inputmethod.keyboard.KeyboardSwitcher; +import com.android.inputmethod.research.ResearchLogger; public class DebugSettings extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { @@ -34,6 +36,7 @@ public class DebugSettings extends PreferenceFragment private static final String TAG = DebugSettings.class.getSimpleName(); private static final String DEBUG_MODE_KEY = "debug_mode"; public static final String FORCE_NON_DISTINCT_MULTITOUCH_KEY = "force_non_distinct_multitouch"; + public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; private boolean mServiceNeedsRestart = false; private CheckBoxPreference mDebugMode; @@ -45,6 +48,14 @@ public class DebugSettings extends PreferenceFragment SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); prefs.registerOnSharedPreferenceChangeListener(this); + final Preference usabilityStudyPref = findPreference(PREF_USABILITY_STUDY_MODE); + if (usabilityStudyPref instanceof CheckBoxPreference) { + final CheckBoxPreference checkbox = (CheckBoxPreference)usabilityStudyPref; + checkbox.setChecked(prefs.getBoolean(PREF_USABILITY_STUDY_MODE, + ResearchLogger.DEFAULT_USABILITY_STUDY_MODE)); + checkbox.setSummary(R.string.settings_warning_researcher_mode); + } + mServiceNeedsRestart = false; mDebugMode = (CheckBoxPreference) findPreference(DEBUG_MODE_KEY); updateDebugMode(); diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 9479a88a7..b984ec367 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -39,12 +39,10 @@ import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; import com.android.inputmethod.latin.define.ProductionFlag; -import com.android.inputmethod.research.ResearchLogger; import com.android.inputmethodcommon.InputMethodSettingsFragment; public final class Settings extends InputMethodSettingsFragment implements SharedPreferences.OnSharedPreferenceChangeListener { - public static final boolean ENABLE_INTERNAL_SETTINGS = ProductionFlag.IS_INTERNAL; // In the same order as xml/prefs.xml public static final String PREF_GENERAL_SETTINGS = "general_settings"; @@ -58,7 +56,6 @@ public final class Settings extends InputMethodSettingsFragment public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold"; public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting"; public static final String PREF_MISC_SETTINGS = "misc_settings"; - public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; public static final String PREF_LAST_USER_DICTIONARY_WRITE_TIME = "last_user_dictionary_write_time"; public static final String PREF_ADVANCED_SETTINGS = "pref_advanced_settings"; @@ -133,14 +130,6 @@ public final class Settings extends InputMethodSettingsFragment mAutoCorrectionThresholdPreference = (ListPreference) findPreference(PREF_AUTO_CORRECTION_THRESHOLD); mBigramPrediction = (CheckBoxPreference) findPreference(PREF_BIGRAM_PREDICTIONS); - mDebugSettingsPreference = findPreference(PREF_DEBUG_SETTINGS); - if (mDebugSettingsPreference != null) { - final Intent debugSettingsIntent = new Intent(Intent.ACTION_MAIN); - debugSettingsIntent.setClassName( - context.getPackageName(), DebugSettings.class.getName()); - mDebugSettingsPreference.setIntent(debugSettingsIntent); - } - ensureConsistencyOfAutoCorrectionSettings(); final PreferenceGroup generalSettings = @@ -150,6 +139,18 @@ public final class Settings extends InputMethodSettingsFragment final PreferenceGroup miscSettings = (PreferenceGroup) findPreference(PREF_MISC_SETTINGS); + mDebugSettingsPreference = findPreference(PREF_DEBUG_SETTINGS); + if (mDebugSettingsPreference != null) { + if (ProductionFlag.IS_INTERNAL) { + final Intent debugSettingsIntent = new Intent(Intent.ACTION_MAIN); + debugSettingsIntent.setClassName( + context.getPackageName(), DebugSettingsActivity.class.getName()); + mDebugSettingsPreference.setIntent(debugSettingsIntent); + } else { + miscSettings.removePreference(mDebugSettingsPreference); + } + } + final boolean showVoiceKeyOption = res.getBoolean( R.bool.config_enable_show_voice_key_option); if (!showVoiceKeyOption) { @@ -218,24 +219,6 @@ public final class Settings extends InputMethodSettingsFragment setPreferenceEnabled(gestureFloatingPreviewText, gestureInputEnabledByUser); } - final boolean showUsabilityStudyModeOption = - res.getBoolean(R.bool.config_enable_usability_study_mode_option) - || ProductionFlag.IS_EXPERIMENTAL || ENABLE_INTERNAL_SETTINGS; - final Preference usabilityStudyPref = findPreference(PREF_USABILITY_STUDY_MODE); - if (!showUsabilityStudyModeOption) { - if (usabilityStudyPref != null) { - miscSettings.removePreference(usabilityStudyPref); - } - } - if (ProductionFlag.IS_EXPERIMENTAL) { - if (usabilityStudyPref instanceof CheckBoxPreference) { - CheckBoxPreference checkbox = (CheckBoxPreference)usabilityStudyPref; - checkbox.setChecked(prefs.getBoolean(PREF_USABILITY_STUDY_MODE, - ResearchLogger.DEFAULT_USABILITY_STUDY_MODE)); - checkbox.setSummary(R.string.settings_warning_researcher_mode); - } - } - mKeypressVibrationDurationSettingsPref = (PreferenceScreen) findPreference(PREF_VIBRATION_DURATION_SETTINGS); if (mKeypressVibrationDurationSettingsPref != null) { diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 9d8379a7a..5b8f1cfb4 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -410,7 +410,7 @@ public final class SettingsValues { // Likewise public static boolean getUsabilityStudyMode(final SharedPreferences prefs) { // TODO: use mUsabilityStudyMode instead of reading it again here - return prefs.getBoolean(Settings.PREF_USABILITY_STUDY_MODE, true); + return prefs.getBoolean(DebugSettings.PREF_USABILITY_STUDY_MODE, true); } public static long getLastUserHistoryWriteTime(final SharedPreferences prefs, -- cgit v1.2.3-83-g751a From 02a67200fc25d1be9dfbc35e3bb4b59bef28f386 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 21 Sep 2012 12:15:02 +0900 Subject: Fix gesture start detection algorithm Bug: 7032858 Change-Id: I9f4d939fa87fdead4c5a5921338a16cd0a59b7ac --- .../inputmethod/keyboard/PointerTracker.java | 10 +- .../keyboard/internal/GestureStroke.java | 161 +++++++++++++++------ .../internal/GestureStrokeWithPreviewPoints.java | 15 +- .../inputmethod/latin/BinaryDictionary.java | 2 +- .../inputmethod/latin/UserHistoryDictionary.java | 2 +- 5 files changed, 127 insertions(+), 63 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 03d610a39..d4902ec28 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -688,7 +688,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { mIsDetectingGesture = true; final int elapsedTimeFromFirstDown = (int)(eventTime - sGestureFirstDownTime); mGestureStrokeWithPreviewPoints.addPoint(x, y, elapsedTimeFromFirstDown, - false /* isHistorical */); + true /* isMajorEvent */); } private void onDownEventInternal(final int x, final int y, final long eventTime) { @@ -724,10 +724,10 @@ public class PointerTracker implements PointerTrackerQueue.Element { } private void onGestureMoveEvent(final int x, final int y, final long eventTime, - final boolean isHistorical, final Key key) { + final boolean isMajorEvent, final Key key) { final int gestureTime = (int)(eventTime - sGestureFirstDownTime); if (mIsDetectingGesture) { - mGestureStrokeWithPreviewPoints.addPoint(x, y, gestureTime, isHistorical); + mGestureStrokeWithPreviewPoints.addPoint(x, y, gestureTime, isMajorEvent); mayStartBatchInput(); if (sInGesture && key != null) { updateBatchInput(eventTime); @@ -752,7 +752,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { final int historicalY = (int)me.getHistoricalY(pointerIndex, h); final long historicalTime = me.getHistoricalEventTime(h); onGestureMoveEvent(historicalX, historicalY, historicalTime, - true /* isHistorical */, null); + false /* isMajorEvent */, null); } } @@ -767,7 +767,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { if (sShouldHandleGesture) { // Register move event on gesture tracker. - onGestureMoveEvent(x, y, eventTime, false /* isHistorical */, key); + onGestureMoveEvent(x, y, eventTime, true /* isMajorEvent */, key); if (sInGesture) { mIgnoreModifierKey = true; mTimerProxy.cancelLongPressTimer(); diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java index f0be0ee94..73413f698 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java +++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java @@ -14,34 +14,45 @@ package com.android.inputmethod.keyboard.internal; +import android.util.Log; + import com.android.inputmethod.latin.InputPointers; import com.android.inputmethod.latin.ResizableIntArray; public class GestureStroke { + private static final String TAG = GestureStroke.class.getSimpleName(); + private static final boolean DEBUG = false; + public static final int DEFAULT_CAPACITY = 128; private final int mPointerId; private final ResizableIntArray mEventTimes = new ResizableIntArray(DEFAULT_CAPACITY); private final ResizableIntArray mXCoordinates = new ResizableIntArray(DEFAULT_CAPACITY); private final ResizableIntArray mYCoordinates = new ResizableIntArray(DEFAULT_CAPACITY); - private float mLength; private int mIncrementalRecognitionSize; private int mLastIncrementalBatchSize; - private long mLastPointTime; - private int mLastPointX; - private int mLastPointY; - - private int mMinGestureLength; // pixel - private int mMinGestureSampleLength; // pixel - private int mGestureRecognitionThreshold; // pixel / sec + private long mLastMajorEventTime; + private int mLastMajorEventX; + private int mLastMajorEventY; + + private int mKeyWidth; + private int mStartGestureLengthThreshold; // pixel + private int mMinGestureSamplingLength; // pixel + private int mGestureRecognitionSpeedThreshold; // pixel / sec + private int mDetectFastMoveSpeedThreshold; // pixel /sec + private int mDetectFastMoveTime; + private int mDetectFastMoveX; + private int mDetectFastMoveY; // TODO: Move some of these to resource. - private static final float MIN_GESTURE_LENGTH_RATIO_TO_KEY_WIDTH = 0.75f; - private static final int MIN_GESTURE_START_DURATION = 100; // msec + private static final float START_GESTURE_LENGTH_THRESHOLD_RATIO_TO_KEY_WIDTH = 0.75f; + private static final int START_GESTURE_DURATION_THRESHOLD = 70; // msec private static final int MIN_GESTURE_RECOGNITION_TIME = 100; // msec private static final float MIN_GESTURE_SAMPLING_RATIO_TO_KEY_WIDTH = 1.0f / 6.0f; private static final float GESTURE_RECOGNITION_SPEED_THRESHOLD_RATIO_TO_KEY_WIDTH = 5.5f; // keyWidth / sec + private static final float DETECT_FAST_MOVE_SPEED_THRESHOLD_RATIO_TO_KEY_WIDTH = + 5.0f; // keyWidth / sec private static final int MSEC_PER_SEC = 1000; public static final boolean hasRecognitionTimePast( @@ -54,64 +65,120 @@ public class GestureStroke { } public void setKeyboardGeometry(final int keyWidth) { + mKeyWidth = keyWidth; // TODO: Find an appropriate base metric for these length. Maybe diagonal length of the key? - mMinGestureLength = (int)(keyWidth * MIN_GESTURE_LENGTH_RATIO_TO_KEY_WIDTH); - mMinGestureSampleLength = (int)(keyWidth * MIN_GESTURE_SAMPLING_RATIO_TO_KEY_WIDTH); - mGestureRecognitionThreshold = + mStartGestureLengthThreshold = + (int)(keyWidth * START_GESTURE_LENGTH_THRESHOLD_RATIO_TO_KEY_WIDTH); + mMinGestureSamplingLength = (int)(keyWidth * MIN_GESTURE_SAMPLING_RATIO_TO_KEY_WIDTH); + mGestureRecognitionSpeedThreshold = (int)(keyWidth * GESTURE_RECOGNITION_SPEED_THRESHOLD_RATIO_TO_KEY_WIDTH); + mDetectFastMoveSpeedThreshold = + (int)(keyWidth * DETECT_FAST_MOVE_SPEED_THRESHOLD_RATIO_TO_KEY_WIDTH); + if (DEBUG) { + Log.d(TAG, "setKeyboardGeometry: keyWidth=" + keyWidth); + } } public boolean isStartOfAGesture() { + if (mDetectFastMoveTime == 0) { + return false; + } final int size = mEventTimes.getLength(); - final int downDuration = (size > 0) ? mEventTimes.get(size - 1) : 0; - return downDuration > MIN_GESTURE_START_DURATION && mLength > mMinGestureLength; + if (size <= 0) { + return false; + } + final int lastIndex = size - 1; + final int deltaTime = mEventTimes.get(lastIndex) - mDetectFastMoveTime; + final int deltaLength = getDistance( + mXCoordinates.get(lastIndex), mYCoordinates.get(lastIndex), + mDetectFastMoveX, mDetectFastMoveY); + final boolean isStartOfAGesture = deltaTime > START_GESTURE_DURATION_THRESHOLD + && deltaLength > mStartGestureLengthThreshold; + if (DEBUG) { + Log.d(TAG, "isStartOfAGesture: dT=" + deltaTime + " dL=" + deltaLength + + " points=" + size + (isStartOfAGesture ? " Detect start of a gesture" : "")); + } + return isStartOfAGesture; } public void reset() { - mLength = 0; mIncrementalRecognitionSize = 0; mLastIncrementalBatchSize = 0; - mLastPointTime = 0; mEventTimes.setLength(0); mXCoordinates.setLength(0); mYCoordinates.setLength(0); + mLastMajorEventTime = 0; + mDetectFastMoveTime = 0; + } + + private void appendPoint(final int x, final int y, final int time) { + mEventTimes.add(time); + mXCoordinates.add(x); + mYCoordinates.add(y); } - public void addPoint(final int x, final int y, final int time, final boolean isHistorical) { - final boolean needsSampling; + private void updateMajorEvent(final int x, final int y, final int time) { + mLastMajorEventTime = time; + mLastMajorEventX = x; + mLastMajorEventY = y; + } + + private int detectFastMove(final int x, final int y, final int time) { final int size = mEventTimes.getLength(); - if (size == 0) { - needsSampling = true; - } else { - final int lastIndex = size - 1; - final int lastX = mXCoordinates.get(lastIndex); - final int lastY = mYCoordinates.get(lastIndex); - final float dist = getDistance(lastX, lastY, x, y); - needsSampling = dist > mMinGestureSampleLength; - mLength += dist; + final int lastIndex = size - 1; + final int lastX = mXCoordinates.get(lastIndex); + final int lastY = mYCoordinates.get(lastIndex); + final int dist = getDistance(lastX, lastY, x, y); + final int msecs = time - mEventTimes.get(lastIndex); + if (msecs > 0) { + final int pixels = getDistance(lastX, lastY, x, y); + final int pixelsPerSec = pixels * MSEC_PER_SEC; + if (DEBUG) { + final float speed = (float)pixelsPerSec / msecs / mKeyWidth; + Log.d(TAG, String.format("Speed=%.3f keyWidth/sec", speed)); + } + // Equivalent to (pixels / msecs < mStartSpeedThreshold / MSEC_PER_SEC) + if (mDetectFastMoveTime == 0 && pixelsPerSec > mDetectFastMoveSpeedThreshold * msecs) { + if (DEBUG) { + Log.d(TAG, "Detect fast move: T=" + time + " points = " + size); + } + mDetectFastMoveTime = time; + mDetectFastMoveX = x; + mDetectFastMoveY = y; + } } - if (needsSampling) { - mEventTimes.add(time); - mXCoordinates.add(x); - mYCoordinates.add(y); + return dist; + } + + public void addPoint(final int x, final int y, final int time, final boolean isMajorEvent) { + final int size = mEventTimes.getLength(); + if (size <= 0) { + // Down event + appendPoint(x, y, time); + updateMajorEvent(x, y, time); + } else { + final int dist = detectFastMove(x, y, time); + if (dist > mMinGestureSamplingLength) { + appendPoint(x, y, time); + } } - if (!isHistorical) { + if (isMajorEvent) { updateIncrementalRecognitionSize(x, y, time); + updateMajorEvent(x, y, time); } } private void updateIncrementalRecognitionSize(final int x, final int y, final int time) { - final int msecs = (int)(time - mLastPointTime); - if (msecs > 0) { - final int pixels = (int)getDistance(mLastPointX, mLastPointY, x, y); - // Equivalent to (pixels / msecs < mGestureRecognitionThreshold / MSEC_PER_SEC) - if (pixels * MSEC_PER_SEC < mGestureRecognitionThreshold * msecs) { - mIncrementalRecognitionSize = mEventTimes.getLength(); - } + final int msecs = (int)(time - mLastMajorEventTime); + if (msecs <= 0) { + return; + } + final int pixels = getDistance(mLastMajorEventX, mLastMajorEventY, x, y); + final int pixelsPerSec = pixels * MSEC_PER_SEC; + // Equivalent to (pixels / msecs < mGestureRecognitionThreshold / MSEC_PER_SEC) + if (pixelsPerSec < mGestureRecognitionSpeedThreshold * msecs) { + mIncrementalRecognitionSize = mEventTimes.getLength(); } - mLastPointTime = time; - mLastPointX = x; - mLastPointY = y; } public void appendAllBatchPoints(final InputPointers out) { @@ -132,11 +199,11 @@ public class GestureStroke { mLastIncrementalBatchSize = size; } - private static float getDistance(final int x1, final int y1, final int x2, final int y2) { - final float dx = x1 - x2; - final float dy = y1 - y2; + private static int getDistance(final int x1, final int y1, final int x2, final int y2) { + final int dx = x1 - x2; + final int dy = y1 - y2; // Note that, in recent versions of Android, FloatMath is actually slower than // java.lang.Math due to the way the JIT optimizes java.lang.Math. - return (float)Math.sqrt(dx * dx + dy * dy); + return (int)Math.sqrt(dx * dx + dy * dy); } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java index ce3914076..3487b5018 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java +++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java @@ -65,21 +65,18 @@ public class GestureStrokeWithPreviewPoints extends GestureStroke { private boolean needsSampling(final int x, final int y) { final int dx = x - mLastX; final int dy = y - mLastY; - final boolean needsSampling = (dx * dx + dy * dy >= mMinPreviewSampleLengthSquare); - if (needsSampling) { - mLastX = x; - mLastY = y; - } - return needsSampling; + return dx * dx + dy * dy >= mMinPreviewSampleLengthSquare; } @Override - public void addPoint(final int x, final int y, final int time, final boolean isHistorical) { - super.addPoint(x, y, time, isHistorical); - if (mPreviewEventTimes.getLength() == 0 || isHistorical || needsSampling(x, y)) { + public void addPoint(final int x, final int y, final int time, final boolean isMajorEvent) { + super.addPoint(x, y, time, isMajorEvent); + if (isMajorEvent || needsSampling(x, y)) { mPreviewEventTimes.add(time); mPreviewXCoordinates.add(x); mPreviewYCoordinates.add(y); + mLastX = x; + mLastY = y; } } diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index c3ae81f3a..9244f16b1 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -45,7 +45,7 @@ public class BinaryDictionary extends Dictionary { public static final int MAX_WORDS = 18; public static final int MAX_SPACES = 16; - private static final String TAG = "BinaryDictionary"; + private static final String TAG = BinaryDictionary.class.getSimpleName(); private static final int MAX_PREDICTIONS = 60; private static final int MAX_RESULTS = Math.max(MAX_PREDICTIONS, MAX_WORDS); diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java index 683ee4f5c..e03af649c 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java @@ -42,7 +42,7 @@ import java.util.concurrent.locks.ReentrantLock; * cancellation or manual picks. This allows the keyboard to adapt to the typist over time. */ public class UserHistoryDictionary extends ExpandableDictionary { - private static final String TAG = "UserHistoryDictionary"; + private static final String TAG = UserHistoryDictionary.class.getSimpleName(); public static final boolean DBG_SAVE_RESTORE = false; public static final boolean DBG_STRESS_TEST = false; public static final boolean DBG_ALWAYS_WRITE = false; -- cgit v1.2.3-83-g751a From 82d9deaaf252cd20f8918adbc7a4b9b8f2647c38 Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Fri, 21 Sep 2012 21:21:58 +0900 Subject: Combine mHasParentAddress with mHasLinkedListNode into mSupportsDynamicUpdate. bug: 6669677 Change-Id: I82799af199358420f09ac34fc005091e202c5d3b --- .../latin/makedict/BinaryDictIOUtils.java | 2 +- .../latin/makedict/BinaryDictInputOutput.java | 35 +++++++++---------- .../inputmethod/latin/makedict/FormatSpec.java | 33 +++++------------- .../latin/makedict/BinaryDictIOTests.java | 40 +++++++++------------- 4 files changed, 42 insertions(+), 68 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 397532933..ac0fb0ece 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -92,7 +92,7 @@ public class BinaryDictIOUtils { } if (p.mPosition == p.mNumOfCharGroup) { - if (formatOptions.mHasLinkedListNode) { + if (formatOptions.mSupportsDynamicUpdate) { final int forwardLinkAddress = buffer.readUnsignedInt24(); if (forwardLinkAddress != FormatSpec.NO_FORWARD_LINK_ADDRESS) { // the node has a forward link. diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 7b8dc5cc5..4806bf9dc 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -376,7 +376,7 @@ public class BinaryDictInputOutput { g.mCachedSize = groupSize; size += groupSize; } - if (options.mHasLinkedListNode) { + if (options.mSupportsDynamicUpdate) { size += FormatSpec.FORWARD_LINK_ADDRESS_SIZE; } node.mCachedSize = size; @@ -390,11 +390,11 @@ public class BinaryDictInputOutput { } /** - * Helper method to check whether the CharGroup has a parent address. + * Helper method to check whether the dictionary can be updated dynamically. */ - public static boolean hasParentAddress(final FormatOptions options) { - return options.mVersion >= FormatSpec.FIRST_VERSION_WITH_PARENT_ADDRESS - && options.mHasParentAddress; + public static boolean supportsDynamicUpdate(final FormatOptions options) { + return options.mVersion >= FormatSpec.FIRST_VERSION_WITH_DYNAMIC_UPDATE + && options.mSupportsDynamicUpdate; } /** @@ -404,7 +404,7 @@ public class BinaryDictInputOutput { * @param options file format options. */ private static int getGroupHeaderSize(final CharGroup group, final FormatOptions options) { - if (hasParentAddress(options)) { + if (supportsDynamicUpdate(options)) { return FormatSpec.GROUP_FLAGS_SIZE + FormatSpec.PARENT_ADDRESS_SIZE + getGroupCharactersSize(group); } else { @@ -530,7 +530,7 @@ public class BinaryDictInputOutput { group.mCachedSize = groupSize; size += groupSize; } - if (formatOptions.mHasLinkedListNode) { + if (formatOptions.mSupportsDynamicUpdate) { size += FormatSpec.FORWARD_LINK_ADDRESS_SIZE; } if (node.mCachedSize != size) { @@ -559,7 +559,8 @@ public class BinaryDictInputOutput { groupOffset += g.mCachedSize; } final int nodeSize = groupCountSize + groupOffset - + (formatOptions.mHasLinkedListNode ? FormatSpec.FORWARD_LINK_ADDRESS_SIZE : 0); + + (formatOptions.mSupportsDynamicUpdate + ? FormatSpec.FORWARD_LINK_ADDRESS_SIZE : 0); if (nodeSize != n.mCachedSize) { throw new RuntimeException("Bug : Stored and computed node size differ"); } @@ -792,8 +793,7 @@ public class BinaryDictInputOutput { return (options.mFrenchLigatureProcessing ? FormatSpec.FRENCH_LIGATURE_PROCESSING_FLAG : 0) + (options.mGermanUmlautProcessing ? FormatSpec.GERMAN_UMLAUT_PROCESSING_FLAG : 0) + (hasBigrams ? FormatSpec.CONTAINS_BIGRAMS_FLAG : 0) - + (formatOptions.mHasParentAddress ? FormatSpec.HAS_PARENT_ADDRESS : 0) - + (formatOptions.mHasLinkedListNode ? FormatSpec.HAS_LINKEDLIST_NODE : 0); + + (formatOptions.mSupportsDynamicUpdate ? FormatSpec.SUPPORTS_DYNAMIC_UPDATE : 0); } /** @@ -857,7 +857,7 @@ public class BinaryDictInputOutput { byte flags = makeCharGroupFlags(group, groupAddress, childrenOffset); buffer[index++] = flags; - if (hasParentAddress(formatOptions)) { + if (supportsDynamicUpdate(formatOptions)) { if (parentAddress == FormatSpec.NO_PARENT_ADDRESS) { // this node is the root node. buffer[index] = buffer[index + 1] = buffer[index + 2] = 0; @@ -927,7 +927,7 @@ public class BinaryDictInputOutput { } } - if (formatOptions.mHasLinkedListNode) { + if (formatOptions.mSupportsDynamicUpdate) { buffer[index] = buffer[index + 1] = buffer[index + 2] = FormatSpec.NO_FORWARD_LINK_ADDRESS; index += FormatSpec.FORWARD_LINK_ADDRESS_SIZE; @@ -1112,7 +1112,7 @@ public class BinaryDictInputOutput { ++addressPointer; final int parentAddress; - if (hasParentAddress(options)) { + if (supportsDynamicUpdate(options)) { // read the parent address. (version 3) parentAddress = -buffer.readUnsignedInt24(); addressPointer += 3; @@ -1251,7 +1251,7 @@ public class BinaryDictInputOutput { final String result; final int originalPointer = buffer.position(); - if (hasParentAddress(formatOptions)) { + if (supportsDynamicUpdate(formatOptions)) { result = getWordAtAddressWithParentAddress(buffer, headerSize, address, formatOptions); } else { result = getWordAtAddressWithoutParentAddress(buffer, headerSize, address, @@ -1392,7 +1392,7 @@ public class BinaryDictInputOutput { } // reach the end of the array. - if (options.mHasLinkedListNode) { + if (options.mSupportsDynamicUpdate) { final int nextAddress = buffer.readUnsignedInt24(); if (nextAddress >= 0 && nextAddress < buffer.limit()) { buffer.position(nextAddress); @@ -1400,7 +1400,7 @@ public class BinaryDictInputOutput { break; } } - } while (options.mHasLinkedListNode && + } while (options.mSupportsDynamicUpdate && buffer.position() != FormatSpec.NO_FORWARD_LINK_ADDRESS); final Node node = new Node(nodeContents); @@ -1469,8 +1469,7 @@ public class BinaryDictInputOutput { 0 != (optionsFlags & FormatSpec.GERMAN_UMLAUT_PROCESSING_FLAG), 0 != (optionsFlags & FormatSpec.FRENCH_LIGATURE_PROCESSING_FLAG)), new FormatOptions(version, - 0 != (optionsFlags & FormatSpec.HAS_PARENT_ADDRESS), - 0 != (optionsFlags & FormatSpec.HAS_LINKEDLIST_NODE))); + 0 != (optionsFlags & FormatSpec.SUPPORTS_DYNAMIC_UPDATE))); return header; } diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index adc6037bb..63a61b46f 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -145,17 +145,14 @@ public final class FormatSpec { static final int MAXIMUM_SUPPORTED_VERSION = 3; static final int NOT_A_VERSION_NUMBER = -1; static final int FIRST_VERSION_WITH_HEADER_SIZE = 2; - static final int FIRST_VERSION_WITH_PARENT_ADDRESS = 3; - static final int FIRST_VERSION_WITH_LINKEDLIST_NODE = 3; + static final int FIRST_VERSION_WITH_DYNAMIC_UPDATE = 3; // These options need to be the same numeric values as the one in the native reading code. static final int GERMAN_UMLAUT_PROCESSING_FLAG = 0x1; // TODO: Make the native reading code read this variable. - static final int HAS_PARENT_ADDRESS = 0x2; + static final int SUPPORTS_DYNAMIC_UPDATE = 0x2; static final int FRENCH_LIGATURE_PROCESSING_FLAG = 0x4; static final int CONTAINS_BIGRAMS_FLAG = 0x8; - // TODO: Make the native reading code read this variable. - static final int HAS_LINKEDLIST_NODE = 0x10; // TODO: Make this value adaptative to content data, store it in the header, and // use it in the reading code. @@ -215,31 +212,17 @@ public final class FormatSpec { */ public static class FormatOptions { public final int mVersion; - public final boolean mHasParentAddress; - public final boolean mHasLinkedListNode; + public final boolean mSupportsDynamicUpdate; public FormatOptions(final int version) { this(version, false); } - public FormatOptions(final int version, final boolean hasParentAddress) { - this(version, hasParentAddress, false); - } - public FormatOptions(final int version, final boolean hasParentAddress, - final boolean hasLinkedListNode) { + public FormatOptions(final int version, final boolean supportsDynamicUpdate) { mVersion = version; - if (version < FIRST_VERSION_WITH_PARENT_ADDRESS && hasParentAddress) { - throw new RuntimeException("Parent addresses are only supported with versions " - + FIRST_VERSION_WITH_PARENT_ADDRESS + " and ulterior."); - } - mHasParentAddress = hasParentAddress; - - if (version < FIRST_VERSION_WITH_LINKEDLIST_NODE && hasLinkedListNode) { - throw new RuntimeException("Linked list nodes are only supported with versions " - + FIRST_VERSION_WITH_LINKEDLIST_NODE + " and ulterior."); - } - if (!hasParentAddress && hasLinkedListNode) { - throw new RuntimeException("Linked list nodes need parent addresses."); + if (version < FIRST_VERSION_WITH_DYNAMIC_UPDATE && supportsDynamicUpdate) { + throw new RuntimeException("Dynamic updates are only supported with versions " + + FIRST_VERSION_WITH_DYNAMIC_UPDATE + " and ulterior."); } - mHasLinkedListNode = hasLinkedListNode; + mSupportsDynamicUpdate = supportsDynamicUpdate; } } diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java index 539021f24..2f954318c 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java +++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java @@ -65,13 +65,10 @@ public class BinaryDictIOTests extends AndroidTestCase { CollectionUtils.newSparseArray(); private static final FormatSpec.FormatOptions VERSION2 = new FormatSpec.FormatOptions(2); - private static final FormatSpec.FormatOptions VERSION3_WITHOUT_PARENTADDRESS = - new FormatSpec.FormatOptions(3, false /* hasParentAddress */); - private static final FormatSpec.FormatOptions VERSION3_WITH_PARENTADDRESS = - new FormatSpec.FormatOptions(3, true /* hasParentAddress */); - private static final FormatSpec.FormatOptions VERSION3_WITH_LINKEDLIST_NODE = - new FormatSpec.FormatOptions(3, true /* hasParentAddress */, - true /* hasLinkedListNode */); + private static final FormatSpec.FormatOptions VERSION3_WITHOUT_DYNAMIC_UPDATE = + new FormatSpec.FormatOptions(3, false /* supportsDynamicUpdate */); + private static final FormatSpec.FormatOptions VERSION3_WITH_DYNAMIC_UPDATE = + new FormatSpec.FormatOptions(3, true /* supportsDynamicUpdate */); private static final String[] CHARACTERS = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", @@ -240,8 +237,7 @@ public class BinaryDictIOTests extends AndroidTestCase { String result = " : buffer type = " + ((bufferType == USE_BYTE_BUFFER) ? "byte buffer" : "byte array"); result += " : version = " + formatOptions.mVersion; - return result + ", hasParentAddress = " + formatOptions.mHasParentAddress - + ", hasLinkedListNode = " + formatOptions.mHasLinkedListNode; + return result + ", supportsDynamicUpdate = " + formatOptions.mSupportsDynamicUpdate; } // Tests for readDictionaryBinary and writeDictionaryBinary @@ -308,9 +304,8 @@ public class BinaryDictIOTests extends AndroidTestCase { final List results = CollectionUtils.newArrayList(); runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION2); - runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION3_WITHOUT_PARENTADDRESS); - runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION3_WITH_PARENTADDRESS); - runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION3_WITH_LINKEDLIST_NODE); + runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION3_WITHOUT_DYNAMIC_UPDATE); + runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION3_WITH_DYNAMIC_UPDATE); for (final String result : results) { Log.d(TAG, result); @@ -321,9 +316,8 @@ public class BinaryDictIOTests extends AndroidTestCase { final List results = CollectionUtils.newArrayList(); runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION2); - runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION3_WITHOUT_PARENTADDRESS); - runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION3_WITH_PARENTADDRESS); - runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION3_WITH_LINKEDLIST_NODE); + runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION3_WITHOUT_DYNAMIC_UPDATE); + runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION3_WITH_DYNAMIC_UPDATE); for (final String result : results) { Log.d(TAG, result); @@ -455,9 +449,8 @@ public class BinaryDictIOTests extends AndroidTestCase { final List results = CollectionUtils.newArrayList(); runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION2); - runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION3_WITHOUT_PARENTADDRESS); - runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION3_WITH_PARENTADDRESS); - runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION3_WITH_LINKEDLIST_NODE); + runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION3_WITHOUT_DYNAMIC_UPDATE); + runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION3_WITH_DYNAMIC_UPDATE); for (final String result : results) { Log.d(TAG, result); @@ -468,9 +461,8 @@ public class BinaryDictIOTests extends AndroidTestCase { final List results = CollectionUtils.newArrayList(); runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION2); - runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION3_WITHOUT_PARENTADDRESS); - runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION3_WITH_PARENTADDRESS); - runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION3_WITH_LINKEDLIST_NODE); + runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION3_WITHOUT_DYNAMIC_UPDATE); + runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION3_WITH_DYNAMIC_UPDATE); for (final String result : results) { Log.d(TAG, result); @@ -528,7 +520,7 @@ public class BinaryDictIOTests extends AndroidTestCase { new FusionDictionary.DictionaryOptions( new HashMap(), false, false)); addUnigrams(sWords.size(), dict, sWords, null /* shortcutMap */); - timeWritingDictToFile(file, dict, VERSION3_WITH_LINKEDLIST_NODE); + timeWritingDictToFile(file, dict, VERSION3_WITH_DYNAMIC_UPDATE); final FusionDictionaryBufferInterface buffer = getBuffer(file, USE_BYTE_ARRAY); @@ -569,7 +561,7 @@ public class BinaryDictIOTests extends AndroidTestCase { public void testDeleteWord() { File file = null; try { - file = File.createTempFile("testGetTerminalPosition", ".dict"); + file = File.createTempFile("testDeleteWord", ".dict"); } catch (IOException e) { // do nothing } @@ -579,7 +571,7 @@ public class BinaryDictIOTests extends AndroidTestCase { new FusionDictionary.DictionaryOptions( new HashMap(), false, false)); addUnigrams(sWords.size(), dict, sWords, null /* shortcutMap */); - timeWritingDictToFile(file, dict, VERSION3_WITH_LINKEDLIST_NODE); + timeWritingDictToFile(file, dict, VERSION3_WITH_DYNAMIC_UPDATE); final FusionDictionaryBufferInterface buffer = getBuffer(file, USE_BYTE_ARRAY); -- cgit v1.2.3-83-g751a From fff8613df04af17bf56db866075b220d1ef0fbe8 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Mon, 24 Sep 2012 14:40:23 +0900 Subject: Fix a race condition with shift Bug: 7062092 Change-Id: Ie1984673e9ffc9291d9650ec38ce99031ad93585 --- java/src/com/android/inputmethod/latin/LatinIME.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 9252b0980..b77eef412 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -856,7 +856,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // TODO: the following is probably better done in resetEntireInputState(). // it should only happen when the cursor moved, and the very purpose of the // test below is to narrow down whether this happened or not. Likewise with - // the call to postUpdateShiftState. + // the call to updateShiftState. // We set this to NONE because after a cursor move, we don't want the space // state-related special processing to kick in. mSpaceState = SPACE_STATE_NONE; @@ -865,7 +865,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen resetEntireInputState(newSelStart); } - mHandler.postUpdateShiftState(); + mKeyboardSwitcher.updateShiftState(); } mExpectingUpdateSelection = false; // TODO: Decide to call restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() or not @@ -1551,7 +1551,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } private void handleBackspace(final int spaceState) { - // In many cases, we may have to put the keyboard in auto-shift state again. + // In many cases, we may have to put the keyboard in auto-shift state again. However + // we want to wait a few milliseconds before doing it to avoid the keyboard flashing + // during key repeat. mHandler.postUpdateShiftState(); if (mWordComposer.isComposingWord()) { @@ -1791,7 +1793,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen Utils.Stats.onSeparator((char)primaryCode, x, y); } - mHandler.postUpdateShiftState(); + mKeyboardSwitcher.updateShiftState(); return didAutoCorrect; } -- cgit v1.2.3-83-g751a From 6efe788494195fb8a57a2317cfa35e01ae7fda13 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Mon, 24 Sep 2012 17:27:03 +0900 Subject: Set punctuation suggestions at start if activated Bug: 7218468 Change-Id: I9f8c1f13dc26cedb95b65279a34a825021dfa72a --- java/src/com/android/inputmethod/latin/LatinIME.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index b77eef412..45ecfd2e7 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -715,7 +715,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mSpaceState = SPACE_STATE_NONE; if (mSuggestionStripView != null) { - mSuggestionStripView.clear(); + // This will set the punctuation suggestions if next word suggestion is off; + // otherwise it will clear the suggestion strip. + setPunctuationSuggestions(); } } -- cgit v1.2.3-83-g751a From 72c5d328882976a0b4ae8b01a872ff5ae4d10547 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Mon, 24 Sep 2012 19:33:42 +0900 Subject: Fix a bug where the cursor pos wouldn't be tracked correctly This would cause Bug: 7208199 Change-Id: I8474985bfe349e1530b27bc98842937627bbe4e0 --- java/src/com/android/inputmethod/latin/LatinIME.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index b77eef412..00608c5c5 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -719,7 +719,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } - mConnection.resetCachesUponCursorMove(mLastSelectionStart); + mConnection.resetCachesUponCursorMove(editorInfo.initialSelStart); if (isDifferentTextField) { mainKeyboardView.closing(); -- cgit v1.2.3-83-g751a From 6a58bb7ac95e804f87c4e88b5eb970d28210518e Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Mon, 24 Sep 2012 16:15:20 +0900 Subject: Add suggestion span upon starting a gesture. Bug: 7196761 Change-Id: If60cb809b205159ced1887f94b7caf9775fcf3bb --- java/src/com/android/inputmethod/latin/LatinIME.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index b77eef412..5712d3b05 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -862,6 +862,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mSpaceState = SPACE_STATE_NONE; if ((!mWordComposer.isComposingWord()) || selectionChanged || noComposingSpan) { + // If we are composing a word and moving the cursor, we would want to set a + // suggestion span for recorrection to work correctly. Unfortunately, that + // would involve the keyboard committing some new text, which would move the + // cursor back to where it was. Latin IME could then fix the position of the cursor + // again, but the asynchronous nature of the calls results in this wreaking havoc + // with selection on double tap and the like. + // Another option would be to send suggestions each time we set the composing + // text, but that is probably too expensive to do, so we decided to leave things + // as is. resetEntireInputState(newSelStart); } @@ -1087,11 +1096,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (!mWordComposer.isComposingWord()) return; final CharSequence typedWord = mWordComposer.getTypedWord(); if (typedWord.length() > 0) { - mConnection.commitText(typedWord, 1); - final CharSequence prevWord = addToUserHistoryDictionary(typedWord); - mLastComposedWord = mWordComposer.commitWord( - LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, typedWord.toString(), - separatorString, prevWord); + commitChosenWord(typedWord, LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, + separatorString); } } -- cgit v1.2.3-83-g751a From 8ec0064c49e80945dbe1bb31129eb890478b7e06 Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Thu, 20 Sep 2012 16:21:40 +0900 Subject: Make children addresses and parent addresses use signed addresses. Signed addresses are used only in version 3 with dynamic update. bug: 6669677 Change-Id: Iadaeab199b5019d2330b4573c24da74d64f0945e --- .../latin/makedict/BinaryDictInputOutput.java | 212 +++++++++++++++------ .../inputmethod/latin/makedict/FormatSpec.java | 21 +- 2 files changed, 166 insertions(+), 67 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 4806bf9dc..d4a4d7cda 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -36,7 +36,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import java.util.Stack; import java.util.TreeMap; /** @@ -412,6 +411,10 @@ public class BinaryDictInputOutput { } } + private static final int UINT8_MAX = 0xFF; + private static final int UINT16_MAX = 0xFFFF; + private static final int UINT24_MAX = 0xFFFFFF; + /** * Compute the size, in bytes, that an address will occupy. * @@ -423,17 +426,25 @@ public class BinaryDictInputOutput { * @return the byte size. */ private static int getByteSize(final int address) { - assert(address < 0x1000000); + assert(address <= UINT24_MAX); if (!hasChildrenAddress(address)) { return 0; - } else if (Math.abs(address) < 0x100) { + } else if (Math.abs(address) <= UINT8_MAX) { return 1; - } else if (Math.abs(address) < 0x10000) { + } else if (Math.abs(address) <= UINT16_MAX) { return 2; } else { return 3; } } + + private static final int SINT8_MAX = 0x7F; + private static final int SINT16_MAX = 0x7FFF; + private static final int SINT24_MAX = 0x7FFFFF; + private static final int MSB8 = 0x80; + private static final int MSB16 = 0x8000; + private static final int MSB24 = 0x800000; + // End utility methods. // This method is responsible for finding a nice ordering of the nodes that favors run-time @@ -509,13 +520,19 @@ public class BinaryDictInputOutput { } int groupSize = getGroupHeaderSize(group, formatOptions); if (group.isTerminal()) groupSize += FormatSpec.GROUP_FREQUENCY_SIZE; - if (null != group.mChildren) { + if (null == group.mChildren && formatOptions.mSupportsDynamicUpdate) { + groupSize += FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE; + } else if (null != group.mChildren) { final int offsetBasePoint = groupSize + node.mCachedAddress + size; final int offset = group.mChildren.mCachedAddress - offsetBasePoint; // assign my address to children's parent address group.mChildren.mCachedParentAddress = group.mCachedAddress - group.mChildren.mCachedAddress; - groupSize += getByteSize(offset); + if (formatOptions.mSupportsDynamicUpdate) { + groupSize += FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE; + } else { + groupSize += getByteSize(offset); + } } groupSize += getShortcutListSize(group.mShortcutTargets); if (null != group.mBigrams) { @@ -669,27 +686,52 @@ public class BinaryDictInputOutput { } } + /** + * Helper method to write a variable-size signed address to a file. + * + * @param buffer the buffer to write to. + * @param index the index in the buffer to write the address to. + * @param address the address to write. + * @return the size in bytes the address actually took. + */ + private static int writeVariableSignedAddress(final byte[] buffer, int index, + final int address) { + if (!hasChildrenAddress(address)) { + buffer[index] = buffer[index + 1] = buffer[index + 2] = 0; + } else { + final int absAddress = Math.abs(address); + buffer[index++] = (byte)((address < 0 ? MSB8 : 0) | (0xFF & (absAddress >> 16))); + buffer[index++] = (byte)(0xFF & (absAddress >> 8)); + buffer[index++] = (byte)(0xFF & absAddress); + } + return 3; + } + private static byte makeCharGroupFlags(final CharGroup group, final int groupAddress, - final int childrenOffset) { + final int childrenOffset, final FormatOptions formatOptions) { byte flags = 0; if (group.mChars.length > 1) flags |= FormatSpec.FLAG_HAS_MULTIPLE_CHARS; if (group.mFrequency >= 0) { flags |= FormatSpec.FLAG_IS_TERMINAL; } if (null != group.mChildren) { - switch (getByteSize(childrenOffset)) { - case 1: - flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_ONEBYTE; - break; - case 2: - flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_TWOBYTES; - break; - case 3: - flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_THREEBYTES; - break; - default: - throw new RuntimeException("Node with a strange address"); - } + final int byteSize = formatOptions.mSupportsDynamicUpdate + ? FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE : getByteSize(childrenOffset); + switch (byteSize) { + case 1: + flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_ONEBYTE; + break; + case 2: + flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_TWOBYTES; + break; + case 3: + flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_THREEBYTES; + break; + default: + throw new RuntimeException("Node with a strange address"); + } + } else if (formatOptions.mSupportsDynamicUpdate) { + flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_THREEBYTES; } if (null != group.mShortcutTargets) { if (DBG && 0 == group.mShortcutTargets.size()) { @@ -808,6 +850,25 @@ public class BinaryDictInputOutput { + (frequency & FormatSpec.FLAG_ATTRIBUTE_FREQUENCY); } + private static final int writeParentAddress(final byte[] buffer, final int index, + final int address, final FormatOptions formatOptions) { + if (supportsDynamicUpdate(formatOptions)) { + if (address == FormatSpec.NO_PARENT_ADDRESS) { + buffer[index] = buffer[index + 1] = buffer[index + 2] = 0; + } else { + final int absAddress = Math.abs(address); + assert(absAddress <= SINT24_MAX); + buffer[index] = (byte)((address < 0 ? MSB8 : 0) + | ((absAddress >> 16) & 0xFF)); + buffer[index + 1] = (byte)((absAddress >> 8) & 0xFF); + buffer[index + 2] = (byte)(absAddress & 0xFF); + } + return index + 3; + } else { + return index; + } + } + /** * Write a node to memory. The node is expected to have its final position cached. * @@ -854,22 +915,15 @@ public class BinaryDictInputOutput { final int childrenOffset = null == group.mChildren ? FormatSpec.NO_CHILDREN_ADDRESS : group.mChildren.mCachedAddress - groupAddress; - byte flags = makeCharGroupFlags(group, groupAddress, childrenOffset); + byte flags = makeCharGroupFlags(group, groupAddress, childrenOffset, formatOptions); buffer[index++] = flags; - if (supportsDynamicUpdate(formatOptions)) { - if (parentAddress == FormatSpec.NO_PARENT_ADDRESS) { - // this node is the root node. - buffer[index] = buffer[index + 1] = buffer[index + 2] = 0; - } else { - // write parent address. (version 3) - final int actualParentAddress = Math.abs(parentAddress - + (node.mCachedAddress - group.mCachedAddress)); - buffer[index] = (byte)((actualParentAddress >> 16) & 0xFF); - buffer[index + 1] = (byte)((actualParentAddress >> 8) & 0xFF); - buffer[index + 2] = (byte)(actualParentAddress & 0xFF); - } - index += 3; + if (parentAddress == FormatSpec.NO_PARENT_ADDRESS) { + index = writeParentAddress(buffer, index, parentAddress, formatOptions); + } else { + index = writeParentAddress(buffer, index, + parentAddress + (node.mCachedAddress - group.mCachedAddress), + formatOptions); } index = CharEncoding.writeCharArray(group.mChars, buffer, index); @@ -879,7 +933,13 @@ public class BinaryDictInputOutput { if (group.mFrequency >= 0) { buffer[index++] = (byte) group.mFrequency; } - final int shift = writeVariableAddress(buffer, index, childrenOffset); + + final int shift; + if (formatOptions.mSupportsDynamicUpdate) { + shift = writeVariableSignedAddress(buffer, index, childrenOffset); + } else { + shift = writeVariableAddress(buffer, index, childrenOffset); + } index += shift; groupAddress += shift; @@ -1104,6 +1164,58 @@ public class BinaryDictInputOutput { // Input methods: Read a binary dictionary to memory. // readDictionaryBinary is the public entry point for them. + private static int getChildrenAddressSize(final int optionFlags, + final FormatOptions formatOptions) { + if (formatOptions.mSupportsDynamicUpdate) return FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE; + switch (optionFlags & FormatSpec.MASK_GROUP_ADDRESS_TYPE) { + case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_ONEBYTE: + return 1; + case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_TWOBYTES: + return 2; + case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_THREEBYTES: + return 3; + case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_NOADDRESS: + default: + return 0; + } + } + + private static int readChildrenAddress(final FusionDictionaryBufferInterface buffer, + final int optionFlags, final FormatOptions options) { + if (options.mSupportsDynamicUpdate) { + final int address = buffer.readUnsignedInt24(); + if (address == 0) return FormatSpec.NO_CHILDREN_ADDRESS; + if ((address & MSB24) != 0) { + return -(address & SINT24_MAX); + } else { + return address; + } + } + int address; + switch (optionFlags & FormatSpec.MASK_GROUP_ADDRESS_TYPE) { + case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_ONEBYTE: + return buffer.readUnsignedByte(); + case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_TWOBYTES: + return buffer.readUnsignedShort(); + case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_THREEBYTES: + return buffer.readUnsignedInt24(); + case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_NOADDRESS: + default: + return FormatSpec.NO_CHILDREN_ADDRESS; + } + } + + private static int readParentAddress(final FusionDictionaryBufferInterface buffer, + final FormatOptions formatOptions) { + if (supportsDynamicUpdate(formatOptions)) { + final int parentAddress = buffer.readUnsignedInt24(); + final int sign = ((parentAddress & MSB24) != 0) ? -1 : 1; + return sign * (parentAddress & SINT24_MAX); + } else { + return FormatSpec.NO_PARENT_ADDRESS; + } + } + private static final int[] CHARACTER_BUFFER = new int[FormatSpec.MAX_WORD_LENGTH]; public static CharGroupInfo readCharGroup(final FusionDictionaryBufferInterface buffer, final int originalGroupAddress, final FormatOptions options) { @@ -1111,13 +1223,9 @@ public class BinaryDictInputOutput { final int flags = buffer.readUnsignedByte(); ++addressPointer; - final int parentAddress; + final int parentAddress = readParentAddress(buffer, options); if (supportsDynamicUpdate(options)) { - // read the parent address. (version 3) - parentAddress = -buffer.readUnsignedInt24(); addressPointer += 3; - } else { - parentAddress = FormatSpec.NO_PARENT_ADDRESS; } final int characters[]; @@ -1146,25 +1254,11 @@ public class BinaryDictInputOutput { } else { frequency = CharGroup.NOT_A_TERMINAL; } - int childrenAddress = addressPointer; - switch (flags & FormatSpec.MASK_GROUP_ADDRESS_TYPE) { - case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_ONEBYTE: - childrenAddress += buffer.readUnsignedByte(); - addressPointer += 1; - break; - case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_TWOBYTES: - childrenAddress += buffer.readUnsignedShort(); - addressPointer += 2; - break; - case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_THREEBYTES: - childrenAddress += buffer.readUnsignedInt24(); - addressPointer += 3; - break; - case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_NOADDRESS: - default: - childrenAddress = FormatSpec.NO_CHILDREN_ADDRESS; - break; + int childrenAddress = readChildrenAddress(buffer, flags, options); + if (childrenAddress != FormatSpec.NO_CHILDREN_ADDRESS) { + childrenAddress += addressPointer; } + addressPointer += getChildrenAddressSize(flags, options); ArrayList shortcutTargets = null; if (0 != (flags & FormatSpec.FLAG_HAS_SHORTCUT_TARGETS)) { final int pointerBefore = buffer.position(); @@ -1250,6 +1344,7 @@ public class BinaryDictInputOutput { final String result; final int originalPointer = buffer.position(); + buffer.position(address); if (supportsDynamicUpdate(formatOptions)) { result = getWordAtAddressWithParentAddress(buffer, headerSize, address, formatOptions); @@ -1279,7 +1374,6 @@ public class BinaryDictInputOutput { sGetWordBuffer[index--] = currentInfo.mCharacters[currentInfo.mCharacters.length - i - 1]; } - if (currentInfo.mParentAddress == FormatSpec.NO_PARENT_ADDRESS) break; currentAddress = currentInfo.mParentAddress + currentInfo.mOriginalAddress; } diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index 63a61b46f..cab0661f6 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -42,11 +42,13 @@ public final class FormatSpec { * ps * * f | - * o | IF HAS_LINKEDLIST_NODE (defined in the file header) + * o | IF SUPPORTS_DYNAMIC_UPDATE (defined in the file header) * r | forward link address, 3byte - * w | the address must be positive. - * a | - * rdlinkaddress + * w | 1 byte = bbbbbbbb match + * a | case 1xxxxxxx => -((xxxxxxx << 16) + (next byte << 8) + next byte) + * r | otherwise => (xxxxxxx << 16) + (next byte << 8) + next byte + * d | + * linkaddress */ /* Node(CharGroup) layout is as follows: @@ -63,11 +65,13 @@ public final class FormatSpec { * | is blacklisted ? 1 bit, 1 = yes, 0 = no : FLAG_IS_BLACKLISTED * * p | - * a | IF HAS_PARENT_ADDRESS (defined in the file header) + * a | IF SUPPORTS_DYNAMIC_UPDATE (defined in the file header) * r | parent address, 3byte - * e | the address must be negative, so the absolute value of the address is stored. - * n | - * taddress + * e | 1 byte = bbbbbbbb match + * n | case 1xxxxxxx => -((0xxxxxxx << 16) + (next byte << 8) + next byte) + * t | otherwise => (bbbbbbbb << 16) + (next byte << 8) + next byte + * a | + * ddress * * c | IF FLAG_HAS_MULTIPLE_CHARS * h | char, char, char, char n * (1 or 3 bytes) : use CharGroupInfo for i/o helpers @@ -206,6 +210,7 @@ public final class FormatSpec { // This option needs to be the same numeric value as the one in binary_format.h. static final int NOT_VALID_WORD = -99; + static final int SIGNED_CHILDREN_ADDRESS_SIZE = 3; /** * Options about file format. -- cgit v1.2.3-83-g751a From 93d7c6233fb6b867d51a9eeb54b951fe3a377ea8 Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Tue, 25 Sep 2012 16:14:16 +0900 Subject: Make getTerminalPosition read linked-list nodes. bug: 6669677 Change-Id: I599d276f430efe23d402695c325e23906b7705b3 --- .../latin/makedict/BinaryDictIOUtils.java | 80 +++++++++++++--------- 1 file changed, 48 insertions(+), 32 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index ac0fb0ece..19da5124a 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -157,47 +157,63 @@ public class BinaryDictIOUtils { final int wordLen = word.codePointCount(0, word.length()); for (int depth = 0; depth < Constants.Dictionary.MAX_WORD_LENGTH; ++depth) { if (wordPos >= wordLen) return FormatSpec.NOT_VALID_WORD; - int groupOffset = buffer.position() - header.mHeaderSize; - final int charGroupCount = BinaryDictInputOutput.readCharGroupCount(buffer); - groupOffset += BinaryDictInputOutput.getGroupCountSize(charGroupCount); - - for (int i = 0; i < charGroupCount; ++i) { - final int charGroupPos = buffer.position(); - final CharGroupInfo currentInfo = BinaryDictInputOutput.readCharGroup(buffer, - buffer.position(), header.mFormatOptions); - boolean same = true; - for (int p = 0, j = word.offsetByCodePoints(0, wordPos); - p < currentInfo.mCharacters.length; - ++p, j = word.offsetByCodePoints(j, 1)) { - if (wordPos + p >= wordLen - || word.codePointAt(j) != currentInfo.mCharacters[p]) { - same = false; - break; + + do { + int groupOffset = buffer.position() - header.mHeaderSize; + final int charGroupCount = BinaryDictInputOutput.readCharGroupCount(buffer); + groupOffset += BinaryDictInputOutput.getGroupCountSize(charGroupCount); + + boolean foundNextCharGroup = false; + for (int i = 0; i < charGroupCount; ++i) { + final int charGroupPos = buffer.position(); + final CharGroupInfo currentInfo = BinaryDictInputOutput.readCharGroup(buffer, + buffer.position(), header.mFormatOptions); + boolean same = true; + for (int p = 0, j = word.offsetByCodePoints(0, wordPos); + p < currentInfo.mCharacters.length; + ++p, j = word.offsetByCodePoints(j, 1)) { + if (wordPos + p >= wordLen + || word.codePointAt(j) != currentInfo.mCharacters[p]) { + same = false; + break; + } } - } - if (same) { - if (wordPos + currentInfo.mCharacters.length == wordLen) { - if (currentInfo.mFrequency == CharGroup.NOT_A_TERMINAL) { + if (same) { + // found the group matches the word. + if (wordPos + currentInfo.mCharacters.length == wordLen) { + if (currentInfo.mFrequency == CharGroup.NOT_A_TERMINAL) { + return FormatSpec.NOT_VALID_WORD; + } else { + return charGroupPos; + } + } + wordPos += currentInfo.mCharacters.length; + if (currentInfo.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS) { return FormatSpec.NOT_VALID_WORD; - } else { - return charGroupPos; } + foundNextCharGroup = true; + buffer.position(currentInfo.mChildrenAddress); + break; } - wordPos += currentInfo.mCharacters.length; - if (currentInfo.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS) { - return FormatSpec.NOT_VALID_WORD; - } - buffer.position(currentInfo.mChildrenAddress); - break; + groupOffset = currentInfo.mEndAddress; } - groupOffset = currentInfo.mEndAddress; - // not found - if (i >= charGroupCount - 1) { + // If we found the next char group, it is under the file pointer. + // But if not, we are at the end of this node so we expect to have + // a forward link address that we need to consult and possibly resume + // search on the next node in the linked list. + if (foundNextCharGroup) break; + if (!header.mFormatOptions.mSupportsDynamicUpdate) { return FormatSpec.NOT_VALID_WORD; } - } + + final int forwardLinkAddress = buffer.readUnsignedInt24(); + if (forwardLinkAddress == FormatSpec.NO_FORWARD_LINK_ADDRESS) { + return FormatSpec.NOT_VALID_WORD; + } + buffer.position(forwardLinkAddress); + } while(true); } return FormatSpec.NOT_VALID_WORD; } -- cgit v1.2.3-83-g751a From a161bdac885fc8e5f0063d33b055b0a6ecdefbdb Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Tue, 25 Sep 2012 17:52:31 +0900 Subject: add capacity to FusionDictionaryBufferInterface. bug: 6669677 Change-Id: I4627093811a19c46ce13fe351d1db63cbd78cf4a --- java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java | 5 +++++ .../android/inputmethod/latin/makedict/BinaryDictInputOutput.java | 6 ++++++ 2 files changed, 11 insertions(+) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java index 4a3d11aa1..05255a6b3 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java @@ -100,6 +100,11 @@ public class UserHistoryDictIOUtils { @Override public int limit() { + return mBuffer.length - 1; + } + + @Override + public int capacity() { return mBuffer.length; } } diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index d4a4d7cda..f9339de08 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -63,6 +63,7 @@ public class BinaryDictInputOutput { public void position(int newPosition); public void put(final byte b); public int limit(); + public int capacity(); } public static final class ByteBufferWrapper implements FusionDictionaryBufferInterface { @@ -112,6 +113,11 @@ public class BinaryDictInputOutput { public int limit() { return mBuffer.limit(); } + + @Override + public int capacity() { + return mBuffer.capacity(); + } } /** -- cgit v1.2.3-83-g751a From 2ee70804e92b17016a2f042c4f6b0e94b5d23e88 Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Tue, 25 Sep 2012 20:48:25 +0900 Subject: Add moved char groups. bug: 6669677 Change-Id: I372f841044fe8e076a50a80ac10b715e5f8fd4eb --- .../latin/makedict/BinaryDictIOUtils.java | 11 +++++++++-- .../latin/makedict/BinaryDictInputOutput.java | 23 ++++++++++++++++++++-- .../inputmethod/latin/makedict/FormatSpec.java | 20 ++++++++++++------- 3 files changed, 43 insertions(+), 11 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 19da5124a..e2c1254ce 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -85,7 +85,10 @@ public class BinaryDictIOUtils { } p.mPosition++; - if (info.mFrequency != FusionDictionary.CharGroup.NOT_A_TERMINAL) { // found word + final boolean isMovedGroup = BinaryDictInputOutput.isMovedGroup(info.mFlags, + formatOptions); + if (!isMovedGroup + && info.mFrequency != FusionDictionary.CharGroup.NOT_A_TERMINAL) {// found word words.put(info.mOriginalAddress, new String(pushedChars, 0, index)); frequencies.put(info.mOriginalAddress, info.mFrequency); if (info.mBigrams != null) bigrams.put(info.mOriginalAddress, info.mBigrams); @@ -109,7 +112,7 @@ public class BinaryDictIOUtils { p.mAddress = buffer.position(); } - if (BinaryDictInputOutput.hasChildrenAddress(info.mChildrenAddress)) { + if (!isMovedGroup && BinaryDictInputOutput.hasChildrenAddress(info.mChildrenAddress)) { Position childrenPos = new Position(info.mChildrenAddress + headerSize, index); stack.push(childrenPos); } @@ -168,6 +171,10 @@ public class BinaryDictIOUtils { final int charGroupPos = buffer.position(); final CharGroupInfo currentInfo = BinaryDictInputOutput.readCharGroup(buffer, buffer.position(), header.mFormatOptions); + if (BinaryDictInputOutput.isMovedGroup(currentInfo.mFlags, + header.mFormatOptions)) { + continue; + } boolean same = true; for (int p = 0, j = word.offsetByCodePoints(0, wordPos); p < currentInfo.mCharacters.length; diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index f9339de08..9fc694218 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -53,6 +53,7 @@ public class BinaryDictInputOutput { // If the number of passes exceeds this number, makedict bails with an exception on // suspicion that a bug might be causing an infinite loop. private static final int MAX_PASSES = 24; + private static final int MAX_JUMPS = 12; public interface FusionDictionaryBufferInterface { public int readUnsignedByte(); @@ -394,6 +395,13 @@ public class BinaryDictInputOutput { return FormatSpec.NO_CHILDREN_ADDRESS != address; } + /** + * Helper method to check whether the group is moved. + */ + public static boolean isMovedGroup(final int flags, final FormatOptions options) { + return options.mSupportsDynamicUpdate && ((flags & FormatSpec.FLAG_IS_MOVED) == 1); + } + /** * Helper method to check whether the dictionary can be updated dynamically. */ @@ -1374,8 +1382,18 @@ public class BinaryDictInputOutput { int index = FormatSpec.MAX_WORD_LENGTH - 1; // the length of the path from the root to the leaf is limited by MAX_WORD_LENGTH for (int count = 0; count < FormatSpec.MAX_WORD_LENGTH; ++count) { - buffer.position(currentAddress + headerSize); - final CharGroupInfo currentInfo = readCharGroup(buffer, currentAddress, options); + CharGroupInfo currentInfo; + int loopCounter = 0; + do { + buffer.position(currentAddress + headerSize); + currentInfo = readCharGroup(buffer, currentAddress, options); + if (isMovedGroup(currentInfo.mFlags, options)) { + currentAddress = currentInfo.mParentAddress + currentInfo.mOriginalAddress; + } + if (DBG && loopCounter++ > MAX_JUMPS) { + MakedictLog.d("Too many jumps - probably a bug"); + } + } while (isMovedGroup(currentInfo.mFlags, options)); for (int i = 0; i < currentInfo.mCharacters.length; ++i) { sGetWordBuffer[index--] = currentInfo.mCharacters[currentInfo.mCharacters.length - i - 1]; @@ -1457,6 +1475,7 @@ public class BinaryDictInputOutput { int groupOffset = nodeHeadPosition + getGroupCountSize(count); for (int i = count; i > 0; --i) { // Scan the array of CharGroup. CharGroupInfo info = readCharGroup(buffer, groupOffset, options); + if (isMovedGroup(info.mFlags, options)) continue; ArrayList shortcutTargets = info.mShortcutTargets; ArrayList bigrams = null; if (null != info.mBigrams) { diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index cab0661f6..35311f0c2 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -52,13 +52,18 @@ public final class FormatSpec { */ /* Node(CharGroup) layout is as follows: - * | addressType xx : mask with MASK_GROUP_ADDRESS_TYPE - * 2 bits, 00 = no children : FLAG_GROUP_ADDRESS_TYPE_NOADDRESS - * f | 01 = 1 byte : FLAG_GROUP_ADDRESS_TYPE_ONEBYTE - * l | 10 = 2 bytes : FLAG_GROUP_ADDRESS_TYPE_TWOBYTES - * a | 11 = 3 bytes : FLAG_GROUP_ADDRESS_TYPE_THREEBYTES - * g | has several chars ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_MULTIPLE_CHARS - * s | has a terminal ? 1 bit, 1 = yes, 0 = no : FLAG_IS_TERMINAL + * | IF !SUPPORTS_DYNAMIC_UPDATE + * | addressType xx : mask with MASK_GROUP_ADDRESS_TYPE + * | 2 bits, 00 = no children : FLAG_GROUP_ADDRESS_TYPE_NOADDRESS + * f | 01 = 1 byte : FLAG_GROUP_ADDRESS_TYPE_ONEBYTE + * l | 10 = 2 bytes : FLAG_GROUP_ADDRESS_TYPE_TWOBYTES + * a | 11 = 3 bytes : FLAG_GROUP_ADDRESS_TYPE_THREEBYTES + * g | ELSE + * s | is moved ? 2 bits, 11 = no + * | 01 = yes + * | the new address is stored in the same place as the parent address + * | has several chars ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_MULTIPLE_CHARS + * | has a terminal ? 1 bit, 1 = yes, 0 = no : FLAG_IS_TERMINAL * | has shortcut targets ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_SHORTCUT_TARGETS * | has bigrams ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_BIGRAMS * | is not a word ? 1 bit, 1 = yes, 0 = no : FLAG_IS_NOT_A_WORD @@ -178,6 +183,7 @@ public final class FormatSpec { static final int FLAG_HAS_BIGRAMS = 0x04; static final int FLAG_IS_NOT_A_WORD = 0x02; static final int FLAG_IS_BLACKLISTED = 0x01; + static final int FLAG_IS_MOVED = 0x40; static final int FLAG_ATTRIBUTE_HAS_NEXT = 0x80; static final int FLAG_ATTRIBUTE_OFFSET_NEGATIVE = 0x40; -- cgit v1.2.3-83-g751a From 2aea34fb31f1a8a5fe24cccd1b9aab4908f2f8e2 Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Wed, 26 Sep 2012 13:21:29 +0900 Subject: Add updateParentAddress. bug: 6669677 Change-Id: I353f8ae53720cdf7a809271a28cb703709609f53 --- .../latin/makedict/BinaryDictIOUtils.java | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index e2c1254ce..b97be0543 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -246,4 +246,34 @@ public class BinaryDictIOUtils { buffer.position(wordPosition); buffer.put((byte)newFlags); } + + private static void putSInt24(final FusionDictionaryBufferInterface buffer, + final int value) { + final int absValue = Math.abs(value); + buffer.put((byte)(((value < 0 ? 0x80 : 0) | (absValue >> 16)) & 0xFF)); + buffer.put((byte)((absValue >> 8) & 0xFF)); + buffer.put((byte)(absValue & 0xFF)); + } + + /** + * Update a parent address in a CharGroup that is addressed by groupOriginAddress. + * + * @param buffer the buffer to write. + * @param groupOriginAddress the address of the group. + * @param newParentAddress the absolute address of the parent. + * @param formatOptions file format options. + */ + public static void updateParentAddress(final FusionDictionaryBufferInterface buffer, + final int groupOriginAddress, final int newParentAddress, + final FormatOptions formatOptions) { + final int originalPosition = buffer.position(); + buffer.position(groupOriginAddress); + if (!formatOptions.mSupportsDynamicUpdate) { + throw new RuntimeException("this file format does not support parent addresses"); + } + final int flags = buffer.readUnsignedByte(); + final int parentOffset = newParentAddress - groupOriginAddress; + putSInt24(buffer, parentOffset); + buffer.position(originalPosition); + } } -- cgit v1.2.3-83-g751a From 84d858ed5e187eb9d4b56b593e1d9287f762bbca Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Mon, 20 Aug 2012 19:29:20 +0900 Subject: Use BinaryDictInputOutput to save UserHistoryDictionary. bug: 6669677 Change-Id: I08193c26f76dbd48168f8ac02c1b737525bfc7b2 --- .../inputmethod/latin/UserHistoryDictIOUtils.java | 28 +- .../inputmethod/latin/UserHistoryDictionary.java | 482 ++++++--------------- .../latin/makedict/BinaryDictIOUtils.java | 5 +- .../latin/UserHistoryDictionaryTests.java | 109 +++++ 4 files changed, 270 insertions(+), 354 deletions(-) create mode 100644 tests/src/com/android/inputmethod/latin/UserHistoryDictionaryTests.java (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java index 05255a6b3..519165dd0 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java @@ -115,11 +115,10 @@ public class UserHistoryDictIOUtils { public static void writeDictionaryBinary(final OutputStream destination, final BigramDictionaryInterface dict, final UserHistoryDictionaryBigramList bigrams, final FormatOptions formatOptions) { - final FusionDictionary fusionDict = constructFusionDictionary(dict, bigrams); - try { BinaryDictInputOutput.writeDictionaryBinary(destination, fusionDict, formatOptions); + Log.d(TAG, "end writing"); } catch (IOException e) { Log.e(TAG, "IO exception while writing file: " + e); } catch (UnsupportedFormatException e) { @@ -132,16 +131,18 @@ public class UserHistoryDictIOUtils { */ /* packages for test */ static FusionDictionary constructFusionDictionary( final BigramDictionaryInterface dict, final UserHistoryDictionaryBigramList bigrams) { - final FusionDictionary fusionDict = new FusionDictionary(new Node(), - new FusionDictionary.DictionaryOptions( - new HashMap(), false, false)); - + new FusionDictionary.DictionaryOptions(new HashMap(), false, + false)); + int profTotal = 0; for (final String word1 : bigrams.keySet()) { final HashMap word1Bigrams = bigrams.getBigrams(word1); for (final String word2 : word1Bigrams.keySet()) { final int freq = dict.getFrequency(word1, word2); - + if (freq == -1) { + // don't add this bigram. + continue; + } if (DEBUG) { if (word1 == null) { Log.d(TAG, "add unigram: " + word2 + "," + Integer.toString(freq)); @@ -149,17 +150,22 @@ public class UserHistoryDictIOUtils { Log.d(TAG, "add bigram: " + word1 + "," + word2 + "," + Integer.toString(freq)); } + profTotal++; } - if (word1 == null) { // unigram fusionDict.add(word2, freq, null, false /* isNotAWord */); } else { // bigram + if (FusionDictionary.findWordInTree(fusionDict.mRoot, word1) == null) { + fusionDict.add(word1, 2, null, false /* isNotAWord */); + } fusionDict.setBigram(word1, word2, freq); } bigrams.updateBigram(word1, word2, (byte)freq); } } - + if (DEBUG) { + Log.d(TAG, "add " + profTotal + "words"); + } return fusionDict; } @@ -171,7 +177,6 @@ public class UserHistoryDictIOUtils { final Map unigrams = CollectionUtils.newTreeMap(); final Map frequencies = CollectionUtils.newTreeMap(); final Map> bigrams = CollectionUtils.newTreeMap(); - try { BinaryDictIOUtils.readUnigramsAndBigramsBinary(buffer, unigrams, frequencies, bigrams); @@ -189,14 +194,11 @@ public class UserHistoryDictIOUtils { /* package for test */ static void addWordsFromWordMap(final Map unigrams, final Map frequencies, final Map> bigrams, final OnAddWordListener to) { - for (Map.Entry entry : unigrams.entrySet()) { final String word1 = entry.getValue(); final int unigramFrequency = frequencies.get(entry.getKey()); to.setUnigram(word1, null, unigramFrequency); - final ArrayList attrList = bigrams.get(entry.getKey()); - if (attrList != null) { for (final PendingAttribute attr : attrList) { to.setBigram(word1, unigrams.get(attr.mAddress), diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java index e03af649c..202aa642f 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java @@ -16,24 +16,25 @@ package com.android.inputmethod.latin; -import android.content.ContentValues; import android.content.Context; import android.content.SharedPreferences; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.database.sqlite.SQLiteQueryBuilder; import android.os.AsyncTask; -import android.provider.BaseColumns; import android.util.Log; import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.UserHistoryDictIOUtils.BigramDictionaryInterface; +import com.android.inputmethod.latin.UserHistoryDictIOUtils.OnAddWordListener; import com.android.inputmethod.latin.UserHistoryForgettingCurveUtils.ForgettingCurveParams; +import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; import java.lang.ref.SoftReference; import java.util.ArrayList; -import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; @@ -43,45 +44,27 @@ import java.util.concurrent.locks.ReentrantLock; */ public class UserHistoryDictionary extends ExpandableDictionary { private static final String TAG = UserHistoryDictionary.class.getSimpleName(); + private static final String NAME = UserHistoryDictionary.class.getSimpleName(); public static final boolean DBG_SAVE_RESTORE = false; public static final boolean DBG_STRESS_TEST = false; public static final boolean DBG_ALWAYS_WRITE = false; public static final boolean PROFILE_SAVE_RESTORE = LatinImeLogger.sDBG; + private static final FormatOptions VERSION3 = new FormatOptions(3, + true /* supportsDynamicUpdate */); + /** Any pair being typed or picked */ private static final int FREQUENCY_FOR_TYPED = 2; /** Maximum number of pairs. Pruning will start when databases goes above this number. */ - public static final int sMaxHistoryBigrams = 10000; + public static final int MAX_HISTORY_BIGRAMS = 10000; /** * When it hits maximum bigram pair, it will delete until you are left with * only (sMaxHistoryBigrams - sDeleteHistoryBigrams) pairs. * Do not keep this number small to avoid deleting too often. */ - public static final int sDeleteHistoryBigrams = 1000; - - /** - * Database version should increase if the database structure changes - */ - private static final int DATABASE_VERSION = 1; - - private static final String DATABASE_NAME = "userbigram_dict.db"; - - /** Name of the words table in the database */ - private static final String MAIN_TABLE_NAME = "main"; - // TODO: Consume less space by using a unique id for locale instead of the whole - // 2-5 character string. - private static final String MAIN_COLUMN_ID = BaseColumns._ID; - private static final String MAIN_COLUMN_WORD1 = "word1"; - private static final String MAIN_COLUMN_WORD2 = "word2"; - private static final String MAIN_COLUMN_LOCALE = "locale"; - - /** Name of the frequency table in the database */ - private static final String FREQ_TABLE_NAME = "frequency"; - private static final String FREQ_COLUMN_ID = BaseColumns._ID; - private static final String FREQ_COLUMN_PAIR_ID = "pair_id"; - private static final String COLUMN_FORGETTING_CURVE_VALUE = "freq"; + public static final int DELETE_HISTORY_BIGRAMS = 1000; /** Locale for which this user history dictionary is storing words */ private final String mLocale; @@ -91,29 +74,13 @@ public class UserHistoryDictionary extends ExpandableDictionary { private final ReentrantLock mBigramListLock = new ReentrantLock(); private final SharedPreferences mPrefs; - private final static HashMap sDictProjectionMap; - private final static ConcurrentHashMap> - sLangDictCache = CollectionUtils.newConcurrentHashMap(); - - static { - sDictProjectionMap = CollectionUtils.newHashMap(); - sDictProjectionMap.put(MAIN_COLUMN_ID, MAIN_COLUMN_ID); - sDictProjectionMap.put(MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD1); - sDictProjectionMap.put(MAIN_COLUMN_WORD2, MAIN_COLUMN_WORD2); - sDictProjectionMap.put(MAIN_COLUMN_LOCALE, MAIN_COLUMN_LOCALE); - - sDictProjectionMap.put(FREQ_COLUMN_ID, FREQ_COLUMN_ID); - sDictProjectionMap.put(FREQ_COLUMN_PAIR_ID, FREQ_COLUMN_PAIR_ID); - sDictProjectionMap.put(COLUMN_FORGETTING_CURVE_VALUE, COLUMN_FORGETTING_CURVE_VALUE); - } - - private static DatabaseHelper sOpenHelper = null; + // Should always be false except when we use this class for test + /* package for test */ boolean isTest = false; - public String getLocale() { - return mLocale; - } + private static final ConcurrentHashMap> + sLangDictCache = CollectionUtils.newConcurrentHashMap(); - public synchronized static UserHistoryDictionary getInstance( + public static synchronized UserHistoryDictionary getInstance( final Context context, final String locale, final SharedPreferences sp) { if (sLangDictCache.containsKey(locale)) { final SoftReference ref = sLangDictCache.get(locale); @@ -136,9 +103,6 @@ public class UserHistoryDictionary extends ExpandableDictionary { super(context, Dictionary.TYPE_USER_HISTORY); mLocale = locale; mPrefs = sp; - if (sOpenHelper == null) { - sOpenHelper = new DatabaseHelper(getContext()); - } if (mLocale != null && mLocale.length() > 1) { loadDictionary(); } @@ -190,6 +154,7 @@ public class UserHistoryDictionary extends ExpandableDictionary { try { super.addWord( word2, null /* the "shortcut" parameter is null */, FREQUENCY_FOR_TYPED); + mBigramList.addBigram(null, word2, (byte)FREQUENCY_FOR_TYPED); // Do not insert a word as a bigram of itself if (word2.equals(word1)) { return 0; @@ -227,11 +192,8 @@ public class UserHistoryDictionary extends ExpandableDictionary { * Schedules a background thread to write any pending words to the database. */ private void flushPendingWrites() { - if (mBigramListLock.isLocked()) { - return; - } // Create a background thread to write the pending entries - new UpdateDbTask(sOpenHelper, mBigramList, mLocale, this, mPrefs).execute(); + new UpdateBinaryTask(mBigramList, mLocale, this, mPrefs, getContext()).execute(); } @Override @@ -245,6 +207,8 @@ public class UserHistoryDictionary extends ExpandableDictionary { } } + private int profTotal; + private void loadDictionaryAsyncLocked() { if (DBG_STRESS_TEST) { try { @@ -257,343 +221,181 @@ public class UserHistoryDictionary extends ExpandableDictionary { final long last = SettingsValues.getLastUserHistoryWriteTime(mPrefs, mLocale); final boolean initializing = last == 0; final long now = System.currentTimeMillis(); - // Load the words that correspond to the current input locale - final Cursor cursor = query(MAIN_COLUMN_LOCALE + "=?", new String[] { mLocale }); - if (null == cursor) return; - try { - // TODO: Call SQLiteDataBase.beginTransaction / SQLiteDataBase.endTransaction - if (cursor.moveToFirst()) { - final int word1Index = cursor.getColumnIndex(MAIN_COLUMN_WORD1); - final int word2Index = cursor.getColumnIndex(MAIN_COLUMN_WORD2); - final int fcIndex = cursor.getColumnIndex(COLUMN_FORGETTING_CURVE_VALUE); - while (!cursor.isAfterLast()) { - final String word1 = cursor.getString(word1Index); - final String word2 = cursor.getString(word2Index); - final int fc = cursor.getInt(fcIndex); + profTotal = 0; + final String fileName = NAME + "." + mLocale + ".dict"; + final ExpandableDictionary dictionary = this; + final OnAddWordListener listener = new OnAddWordListener() { + @Override + public void setUnigram(String word, String shortcutTarget, int frequency) { + profTotal++; + if (DBG_SAVE_RESTORE) { + Log.d(TAG, "load unigram: " + word + "," + frequency); + } + dictionary.addWord(word, shortcutTarget, frequency); + mBigramList.addBigram(null, word, (byte)frequency); + } + + @Override + public void setBigram(String word1, String word2, int frequency) { + if (word1.length() < BinaryDictionary.MAX_WORD_LENGTH + && word2.length() < BinaryDictionary.MAX_WORD_LENGTH) { + profTotal++; if (DBG_SAVE_RESTORE) { - Log.d(TAG, "--- Load user history: " + word1 + ", " + word2 + "," - + mLocale + "," + this); - } - // Safeguard against adding really long words. Stack may overflow due - // to recursive lookup - if (null == word1) { - super.addWord(word2, null /* shortcut */, fc); - } else if (word1.length() < BinaryDictionary.MAX_WORD_LENGTH - && word2.length() < BinaryDictionary.MAX_WORD_LENGTH) { - super.setBigramAndGetFrequency( - word1, word2, initializing ? new ForgettingCurveParams(true) - : new ForgettingCurveParams(fc, now, last)); + Log.d(TAG, "load bigram: " + word1 + "," + word2 + "," + frequency); } - mBigramList.addBigram(word1, word2, (byte)fc); - cursor.moveToNext(); + dictionary.setBigramAndGetFrequency( + word1, word2, initializing ? new ForgettingCurveParams(true) + : new ForgettingCurveParams(frequency, now, last)); } + mBigramList.addBigram(word1, word2, (byte)frequency); } + }; + + // Load the dictionary from binary file + FileInputStream inStream = null; + try { + final File file = new File(getContext().getFilesDir(), fileName); + final byte[] buffer = new byte[(int)file.length()]; + inStream = new FileInputStream(file); + inStream.read(buffer); + UserHistoryDictIOUtils.readDictionaryBinary( + new UserHistoryDictIOUtils.ByteArrayWrapper(buffer), listener); + } catch (FileNotFoundException e) { + Log.e(TAG, "when loading: file not found" + e); + } catch (IOException e) { + Log.e(TAG, "IOException when open bytebuffer: " + e); } finally { - cursor.close(); + if (inStream != null) { + try { + inStream.close(); + } catch (IOException e) { + // do nothing + } + } if (PROFILE_SAVE_RESTORE) { final long diff = System.currentTimeMillis() - now; - Log.w(TAG, "PROF: Load User HistoryDictionary: " - + mLocale + ", " + diff + "ms."); + Log.d(TAG, "PROF: Load UserHistoryDictionary: " + + mLocale + ", " + diff + "ms. load " + profTotal + "entries."); } } } /** - * Query the database + * Async task to write pending words to the binarydicts. */ - private static Cursor query(String selection, String[] selectionArgs) { - SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); - - // main INNER JOIN frequency ON (main._id=freq.pair_id) - qb.setTables(MAIN_TABLE_NAME + " INNER JOIN " + FREQ_TABLE_NAME + " ON (" - + MAIN_TABLE_NAME + "." + MAIN_COLUMN_ID + "=" + FREQ_TABLE_NAME + "." - + FREQ_COLUMN_PAIR_ID +")"); - - qb.setProjectionMap(sDictProjectionMap); - - // Get the database and run the query - try { - SQLiteDatabase db = sOpenHelper.getReadableDatabase(); - Cursor c = qb.query(db, - new String[] { - MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD2, COLUMN_FORGETTING_CURVE_VALUE }, - selection, selectionArgs, null, null, null); - return c; - } catch (android.database.sqlite.SQLiteCantOpenDatabaseException e) { - // Can't open the database : presumably we can't access storage. That may happen - // when the device is wedged; do a best effort to still start the keyboard. - return null; - } - } - - /** - * This class helps open, create, and upgrade the database file. - */ - private static class DatabaseHelper extends SQLiteOpenHelper { - - DatabaseHelper(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL("PRAGMA foreign_keys = ON;"); - db.execSQL("CREATE TABLE " + MAIN_TABLE_NAME + " (" - + MAIN_COLUMN_ID + " INTEGER PRIMARY KEY," - + MAIN_COLUMN_WORD1 + " TEXT," - + MAIN_COLUMN_WORD2 + " TEXT," - + MAIN_COLUMN_LOCALE + " TEXT" - + ");"); - db.execSQL("CREATE TABLE " + FREQ_TABLE_NAME + " (" - + FREQ_COLUMN_ID + " INTEGER PRIMARY KEY," - + FREQ_COLUMN_PAIR_ID + " INTEGER," - + COLUMN_FORGETTING_CURVE_VALUE + " INTEGER," - + "FOREIGN KEY(" + FREQ_COLUMN_PAIR_ID + ") REFERENCES " + MAIN_TABLE_NAME - + "(" + MAIN_COLUMN_ID + ")" + " ON DELETE CASCADE" - + ");"); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - Log.w(TAG, "Upgrading database from version " + oldVersion + " to " - + newVersion + ", which will destroy all old data"); - db.execSQL("DROP TABLE IF EXISTS " + MAIN_TABLE_NAME); - db.execSQL("DROP TABLE IF EXISTS " + FREQ_TABLE_NAME); - onCreate(db); - } - } - - /** - * Async task to write pending words to the database so that it stays in sync with - * the in-memory trie. - */ - private static class UpdateDbTask extends AsyncTask { + private static class UpdateBinaryTask extends AsyncTask + implements BigramDictionaryInterface { private final UserHistoryDictionaryBigramList mBigramList; - private final DatabaseHelper mDbHelper; + private final boolean mAddLevel0Bigrams; private final String mLocale; private final UserHistoryDictionary mUserHistoryDictionary; private final SharedPreferences mPrefs; + private final Context mContext; - public UpdateDbTask( - DatabaseHelper openHelper, UserHistoryDictionaryBigramList pendingWrites, - String locale, UserHistoryDictionary dict, SharedPreferences prefs) { + public UpdateBinaryTask(UserHistoryDictionaryBigramList pendingWrites, String locale, + UserHistoryDictionary dict, SharedPreferences prefs, Context context) { mBigramList = pendingWrites; mLocale = locale; - mDbHelper = openHelper; mUserHistoryDictionary = dict; mPrefs = prefs; - } - - /** Prune any old data if the database is getting too big. */ - private static void checkPruneData(SQLiteDatabase db) { - db.execSQL("PRAGMA foreign_keys = ON;"); - Cursor c = db.query(FREQ_TABLE_NAME, new String[] { FREQ_COLUMN_PAIR_ID }, - null, null, null, null, null); - try { - int totalRowCount = c.getCount(); - // prune out old data if we have too much data - if (totalRowCount > sMaxHistoryBigrams) { - int numDeleteRows = (totalRowCount - sMaxHistoryBigrams) - + sDeleteHistoryBigrams; - int pairIdColumnId = c.getColumnIndex(FREQ_COLUMN_PAIR_ID); - c.moveToFirst(); - int count = 0; - while (count < numDeleteRows && !c.isAfterLast()) { - String pairId = c.getString(pairIdColumnId); - // Deleting from MAIN table will delete the frequencies - // due to FOREIGN KEY .. ON DELETE CASCADE - db.delete(MAIN_TABLE_NAME, MAIN_COLUMN_ID + "=?", - new String[] { pairId }); - c.moveToNext(); - count++; - } - } - } finally { - c.close(); - } + mContext = context; + mAddLevel0Bigrams = mBigramList.size() <= MAX_HISTORY_BIGRAMS; } @Override protected Void doInBackground(Void... v) { - SQLiteDatabase db = null; - if (mUserHistoryDictionary.mBigramListLock.tryLock()) { + if (mUserHistoryDictionary.isTest) { + // If isTest == true, wait until the lock is released. + mUserHistoryDictionary.mBigramListLock.lock(); try { - try { - db = mDbHelper.getWritableDatabase(); - } catch (android.database.sqlite.SQLiteCantOpenDatabaseException e) { - // If we can't open the db, don't do anything. Exit through the next test - // for non-nullity of the db variable. - } - if (null == db) { - // Not much we can do. Just exit. - return null; - } - db.beginTransaction(); - return doLoadTaskLocked(db); + doWriteTaskLocked(); } finally { - if (db != null) { - db.endTransaction(); - } mUserHistoryDictionary.mBigramListLock.unlock(); } + } else if (mUserHistoryDictionary.mBigramListLock.tryLock()) { + doWriteTaskLocked(); } return null; } - private Void doLoadTaskLocked(SQLiteDatabase db) { + private void doWriteTaskLocked() { if (DBG_STRESS_TEST) { try { Log.w(TAG, "Start stress in closing: " + mLocale); Thread.sleep(15000); Log.w(TAG, "End stress in closing"); } catch (InterruptedException e) { + Log.e(TAG, "In stress test: " + e); } } + final long now = PROFILE_SAVE_RESTORE ? System.currentTimeMillis() : 0; - int profTotal = 0; - int profInsert = 0; - int profDelete = 0; - db.execSQL("PRAGMA foreign_keys = ON;"); - final boolean addLevel0Bigram = mBigramList.size() <= sMaxHistoryBigrams; - - // Write all the entries to the db - for (String word1 : mBigramList.keySet()) { - final HashMap word1Bigrams = mBigramList.getBigrams(word1); - for (String word2 : word1Bigrams.keySet()) { - if (PROFILE_SAVE_RESTORE) { - ++profTotal; - } - // Get new frequency. Do not insert unigrams/bigrams which freq is "-1". - final int freq; // -1, or 0~255 - if (word1 == null) { // unigram - freq = FREQUENCY_FOR_TYPED; - final byte prevFc = word1Bigrams.get(word2); - if (prevFc == FREQUENCY_FOR_TYPED) { - // No need to update since we found no changes for this entry. - // Just skip to the next entry. - if (DBG_SAVE_RESTORE) { - Log.d(TAG, "Skip update user history: " + word1 + "," + word2 - + "," + prevFc); - } - if (!DBG_ALWAYS_WRITE) { - continue; - } - } - } else { // bigram - final NextWord nw = mUserHistoryDictionary.getBigramWord(word1, word2); - if (nw != null) { - final ForgettingCurveParams fcp = nw.getFcParams(); - final byte prevFc = word1Bigrams.get(word2); - final byte fc = (byte)fcp.getFc(); - final boolean isValid = fcp.isValid(); - if (prevFc > 0 && prevFc == fc) { - // No need to update since we found no changes for this entry. - // Just skip to the next entry. - if (DBG_SAVE_RESTORE) { - Log.d(TAG, "Skip update user history: " + word1 + "," - + word2 + "," + prevFc); - } - if (!DBG_ALWAYS_WRITE) { - continue; - } else { - freq = fc; - } - } else if (UserHistoryForgettingCurveUtils. - needsToSave(fc, isValid, addLevel0Bigram)) { - freq = fc; - } else { - // Delete this entry - freq = -1; - } - } else { - // Delete this entry - freq = -1; - } - } - // TODO: this process of making a text search for each pair each time - // is terribly inefficient. Optimize this. - // Find pair id - Cursor c = null; + final String fileName = NAME + "." + mLocale + ".dict"; + final File file = new File(mContext.getFilesDir(), fileName); + FileOutputStream out = null; + + try { + out = new FileOutputStream(file); + UserHistoryDictIOUtils.writeDictionaryBinary(out, this, mBigramList, VERSION3); + out.flush(); + out.close(); + } catch (IOException e) { + Log.e(TAG, "IO Exception while writing file: " + e); + } finally { + if (out != null) { try { - if (null != word1) { - c = db.query(MAIN_TABLE_NAME, new String[] { MAIN_COLUMN_ID }, - MAIN_COLUMN_WORD1 + "=? AND " + MAIN_COLUMN_WORD2 + "=? AND " - + MAIN_COLUMN_LOCALE + "=?", - new String[] { word1, word2, mLocale }, null, null, - null); - } else { - c = db.query(MAIN_TABLE_NAME, new String[] { MAIN_COLUMN_ID }, - MAIN_COLUMN_WORD1 + " IS NULL AND " + MAIN_COLUMN_WORD2 - + "=? AND " + MAIN_COLUMN_LOCALE + "=?", - new String[] { word2, mLocale }, null, null, null); - } - - final int pairId; - if (c.moveToFirst()) { - if (PROFILE_SAVE_RESTORE) { - ++profDelete; - } - // Delete existing pair - pairId = c.getInt(c.getColumnIndex(MAIN_COLUMN_ID)); - db.delete(FREQ_TABLE_NAME, FREQ_COLUMN_PAIR_ID + "=?", - new String[] { Integer.toString(pairId) }); - } else { - // Create new pair - Long pairIdLong = db.insert(MAIN_TABLE_NAME, null, - getContentValues(word1, word2, mLocale)); - pairId = pairIdLong.intValue(); - } - // Eliminate freq == 0 because that word is profanity. - if (freq > 0) { - if (PROFILE_SAVE_RESTORE) { - ++profInsert; - } - if (DBG_SAVE_RESTORE) { - Log.d(TAG, "--- Save user history: " + word1 + ", " + word2 - + mLocale + "," + this); - } - // Insert new frequency - db.insert(FREQ_TABLE_NAME, null, - getFrequencyContentValues(pairId, freq)); - // Update an existing bigram entry in mBigramList too in order to - // synchronize the SQL DB and mBigramList. - mBigramList.updateBigram(word1, word2, (byte)freq); - } - } finally { - if (c != null) { - c.close(); - } + out.close(); + } catch (IOException e) { + // ignore } } } - checkPruneData(db); - // Save the timestamp after we finish writing the SQL DB. + // Save the timestamp after we finish writing the binary dictionary. SettingsValues.setLastUserHistoryWriteTime(mPrefs, mLocale); if (PROFILE_SAVE_RESTORE) { final long diff = System.currentTimeMillis() - now; - Log.w(TAG, "PROF: Write User HistoryDictionary: " + mLocale + ", "+ diff - + "ms. Total: " + profTotal + ". Insert: " + profInsert + ". Delete: " - + profDelete); + Log.w(TAG, "PROF: Write User HistoryDictionary: " + mLocale + ", " + diff + "ms."); } - db.setTransactionSuccessful(); - return null; } - private static ContentValues getContentValues(String word1, String word2, String locale) { - ContentValues values = new ContentValues(3); - values.put(MAIN_COLUMN_WORD1, word1); - values.put(MAIN_COLUMN_WORD2, word2); - values.put(MAIN_COLUMN_LOCALE, locale); - return values; + @Override + public int getFrequency(String word1, String word2) { + final int freq; + if (word1 == null) { // unigram + freq = FREQUENCY_FOR_TYPED; + final byte prevFc = mBigramList.getBigrams(word1).get(word2); + } else { // bigram + final NextWord nw = mUserHistoryDictionary.getBigramWord(word1, word2); + if (nw != null) { + final ForgettingCurveParams fcp = nw.getFcParams(); + final byte prevFc = mBigramList.getBigrams(word1).get(word2); + final byte fc = fcp.getFc(); + final boolean isValid = fcp.isValid(); + if (prevFc > 0 && prevFc == fc) { + freq = ((int)fc) & 0xFF; + } else if (UserHistoryForgettingCurveUtils. + needsToSave(fc, isValid, mAddLevel0Bigrams)) { + freq = ((int)fc) & 0xFF; + } else { + // Delete this entry + freq = -1; + } + } else { + // Delete this entry + freq = -1; + } + } + return freq; } + } - private static ContentValues getFrequencyContentValues(int pairId, int frequency) { - ContentValues values = new ContentValues(2); - values.put(FREQ_COLUMN_PAIR_ID, pairId); - values.put(COLUMN_FORGETTING_CURVE_VALUE, frequency); - return values; + void forceAddWordForTest(final String word1, final String word2, final boolean isValid) { + mBigramListLock.lock(); + try { + addToUserHistory(word1, word2, isValid); + } finally { + mBigramListLock.unlock(); } } - } diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index b97be0543..a1606db60 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -77,7 +77,10 @@ public class BinaryDictIOUtils { p.mAddress += BinaryDictInputOutput.getGroupCountSize(p.mNumOfCharGroup); p.mPosition = 0; } - + if (p.mNumOfCharGroup == 0) { + stack.pop(); + continue; + } CharGroupInfo info = BinaryDictInputOutput.readCharGroup(buffer, p.mAddress - headerSize, formatOptions); for (int i = 0; i < info.mCharacters.length; ++i) { diff --git a/tests/src/com/android/inputmethod/latin/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/UserHistoryDictionaryTests.java new file mode 100644 index 000000000..f2a17d206 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/UserHistoryDictionaryTests.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin; + +import com.android.inputmethod.latin.UserHistoryDictionary; + +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.test.AndroidTestCase; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.Set; + +/** + * Unit tests for UserHistoryDictionary + */ +public class UserHistoryDictionaryTests extends AndroidTestCase { + private static final String TAG = UserHistoryDictionaryTests.class.getSimpleName(); + private SharedPreferences mPrefs; + + private static final String[] CHARACTERS = { + "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", + "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" + }; + + @Override + public void setUp() { + mPrefs = PreferenceManager.getDefaultSharedPreferences(getContext()); + } + + /** + * Generates a random word. + */ + private String generateWord(final int value) { + final int lengthOfChars = CHARACTERS.length; + StringBuilder builder = new StringBuilder(); + long lvalue = Math.abs((long)value); + while (lvalue > 0) { + builder.append(CHARACTERS[(int)(lvalue % lengthOfChars)]); + lvalue /= lengthOfChars; + } + return builder.toString(); + } + + private List generateWords(final int number, final Random random) { + final Set wordSet = CollectionUtils.newHashSet(); + while (wordSet.size() < number) { + wordSet.add(generateWord(random.nextInt())); + } + return new ArrayList(wordSet); + } + + private void addToDict(final UserHistoryDictionary dict, final List words) { + String prevWord = null; + for (String word : words) { + dict.forceAddWordForTest(prevWord, word, true); + prevWord = word; + } + } + + public void testRandomWords() { + Log.d(TAG, "This test can be used for profiling."); + Log.d(TAG, "Usage: please set UserHisotoryDictionary.PROFILE_SAVE_RESTORE to true."); + final int numberOfWords = 1000; + final Random random = new Random(123456); + List words = generateWords(numberOfWords, random); + + final String locale = "testRandomWords"; + final UserHistoryDictionary dict = UserHistoryDictionary.getInstance(getContext(), + locale, mPrefs); + dict.isTest = true; + + addToDict(dict, words); + + try { + Log.d(TAG, "waiting for adding the word ..."); + Thread.sleep(2000); + } catch (InterruptedException e) { + Log.d(TAG, "InterruptedException: " + e); + } + + // write to file + dict.close(); + + try { + Log.d(TAG, "waiting for writing ..."); + Thread.sleep(5000); + } catch (InterruptedException e) { + Log.d(TAG, "InterruptedException: " + e); + } + } +} -- cgit v1.2.3-83-g751a From a28a05e971cc242b338331a3b78276fa95188d19 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 27 Sep 2012 18:16:16 +0900 Subject: Cleanup: Make some classes as final Change-Id: I6009b3c1950ba32b7f1e205a3db2307fe0cd688e --- .../accessibility/AccessibilityEntityProvider.java | 2 +- .../accessibility/AccessibleKeyboardViewProxy.java | 2 +- .../accessibility/KeyCodeDescriptionMapper.java | 2 +- .../inputmethod/compat/AudioManagerCompatWrapper.java | 2 +- .../compat/InputMethodManagerCompatWrapper.java | 2 +- java/src/com/android/inputmethod/keyboard/Key.java | 2 +- .../com/android/inputmethod/keyboard/KeyboardId.java | 2 +- .../inputmethod/keyboard/KeyboardLayoutSet.java | 10 +++++----- .../android/inputmethod/keyboard/KeyboardSwitcher.java | 4 ++-- .../android/inputmethod/keyboard/MainKeyboardView.java | 4 ++-- .../android/inputmethod/keyboard/MoreKeysDetector.java | 2 +- .../android/inputmethod/keyboard/MoreKeysKeyboard.java | 2 +- .../inputmethod/keyboard/MoreKeysKeyboardView.java | 2 +- .../android/inputmethod/keyboard/PointerTracker.java | 4 ++-- .../keyboard/internal/AlphabetShiftState.java | 2 +- .../internal/GestureStrokeWithPreviewPoints.java | 2 +- .../inputmethod/keyboard/internal/KeySpecParser.java | 4 ++-- .../inputmethod/keyboard/internal/KeyStylesSet.java | 6 +++--- .../keyboard/internal/KeyVisualAttributes.java | 2 +- .../keyboard/internal/KeyboardCodesSet.java | 2 +- .../keyboard/internal/KeyboardIconsSet.java | 2 +- .../inputmethod/keyboard/internal/KeyboardRow.java | 2 +- .../inputmethod/keyboard/internal/KeyboardState.java | 4 ++-- .../inputmethod/keyboard/internal/KeysCache.java | 2 +- .../keyboard/internal/PointerTrackerQueue.java | 2 +- .../keyboard/internal/PreviewPlacerView.java | 4 ++-- .../inputmethod/keyboard/internal/ShiftKeyState.java | 2 +- .../internal/SuddenJumpingTouchEventHandler.java | 2 +- .../inputmethod/latin/AdditionalSubtypeSettings.java | 2 +- .../android/inputmethod/latin/AssetFileAddress.java | 2 +- .../latin/AudioAndHapticFeedbackManager.java | 2 +- .../com/android/inputmethod/latin/AutoCorrection.java | 2 +- .../src/com/android/inputmethod/latin/BackupAgent.java | 2 +- .../android/inputmethod/latin/BinaryDictionary.java | 2 +- .../inputmethod/latin/BinaryDictionaryFileDumper.java | 3 +-- .../inputmethod/latin/BinaryDictionaryGetter.java | 6 +++--- .../com/android/inputmethod/latin/BoundedTreeSet.java | 2 +- .../com/android/inputmethod/latin/DebugSettings.java | 2 +- .../inputmethod/latin/DebugSettingsActivity.java | 2 +- .../android/inputmethod/latin/DicTraverseSession.java | 2 +- .../inputmethod/latin/DictionaryCollection.java | 2 +- .../android/inputmethod/latin/DictionaryFactory.java | 2 +- .../latin/DictionaryPackInstallBroadcastReceiver.java | 2 +- .../inputmethod/latin/ExpandableDictionary.java | 10 +++++----- .../com/android/inputmethod/latin/FileTransforms.java | 2 +- .../com/android/inputmethod/latin/InputAttributes.java | 2 +- .../com/android/inputmethod/latin/InputPointers.java | 2 +- java/src/com/android/inputmethod/latin/InputView.java | 2 +- .../android/inputmethod/latin/LastComposedWord.java | 2 +- java/src/com/android/inputmethod/latin/LatinIME.java | 4 ++-- .../com/android/inputmethod/latin/LatinImeLogger.java | 2 +- .../android/inputmethod/latin/ResizableIntArray.java | 2 +- .../android/inputmethod/latin/RichInputConnection.java | 4 ++-- .../android/inputmethod/latin/SettingsActivity.java | 2 +- .../com/android/inputmethod/latin/SubtypeLocale.java | 2 +- .../com/android/inputmethod/latin/SubtypeSwitcher.java | 4 ++-- java/src/com/android/inputmethod/latin/Suggest.java | 5 +++-- .../com/android/inputmethod/latin/SuggestedWords.java | 4 ++-- .../SuggestionSpanPickedNotificationReceiver.java | 2 +- .../SynchronouslyLoadedContactsBinaryDictionary.java | 2 +- .../latin/SynchronouslyLoadedUserBinaryDictionary.java | 2 +- .../inputmethod/latin/TargetApplicationGetter.java | 4 ++-- .../inputmethod/latin/UserHistoryDictIOUtils.java | 2 +- .../inputmethod/latin/UserHistoryDictionary.java | 4 ++-- .../latin/UserHistoryDictionaryBigramList.java | 2 +- .../latin/UserHistoryForgettingCurveUtils.java | 4 ++-- .../com/android/inputmethod/latin/WordComposer.java | 2 +- .../com/android/inputmethod/latin/WordListInfo.java | 2 +- .../com/android/inputmethod/latin/XmlParseUtils.java | 8 ++++---- .../inputmethod/latin/makedict/BinaryDictIOUtils.java | 4 ++-- .../latin/makedict/BinaryDictInputOutput.java | 4 ++-- .../inputmethod/latin/makedict/CharGroupInfo.java | 2 +- .../android/inputmethod/latin/makedict/FormatSpec.java | 2 +- .../inputmethod/latin/makedict/FusionDictionary.java | 18 ++++++++---------- .../inputmethod/latin/makedict/MakedictLog.java | 2 +- .../inputmethod/latin/makedict/PendingAttribute.java | 2 +- .../latin/makedict/UnsupportedFormatException.java | 2 +- .../com/android/inputmethod/latin/makedict/Word.java | 2 +- .../latin/spellcheck/AndroidSpellCheckerService.java | 6 +++--- .../latin/spellcheck/AndroidSpellCheckerSession.java | 2 +- .../AndroidWordLevelSpellCheckerSession.java | 4 ++-- .../inputmethod/latin/spellcheck/DictAndProximity.java | 2 +- .../inputmethod/latin/spellcheck/DictionaryPool.java | 2 +- .../latin/spellcheck/SpellCheckerProximityInfo.java | 6 +++--- .../latin/spellcheck/SpellCheckerSettingsActivity.java | 2 +- .../latin/spellcheck/SpellCheckerSettingsFragment.java | 2 +- .../inputmethod/latin/suggestions/MoreSuggestions.java | 8 ++++---- .../latin/suggestions/MoreSuggestionsView.java | 2 +- .../latin/suggestions/SuggestionStripView.java | 6 +++--- 89 files changed, 138 insertions(+), 140 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java index 5af5d044f..b9b6362fc 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java @@ -47,7 +47,7 @@ import com.android.inputmethod.latin.CollectionUtils; * virtual views, thus conveying their logical structure. *

*/ -public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat { +public final class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat { private static final String TAG = AccessibilityEntityProvider.class.getSimpleName(); private static final int UNDEFINED = Integer.MIN_VALUE; diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java index 01220a58a..fcfa6d4e4 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java @@ -32,7 +32,7 @@ import com.android.inputmethod.keyboard.MainKeyboardView; import com.android.inputmethod.keyboard.PointerTracker; import com.android.inputmethod.latin.R; -public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat { +public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat { private static final AccessibleKeyboardViewProxy sInstance = new AccessibleKeyboardViewProxy(); private InputMethodService mInputMethod; diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java index 5c45448a5..32618ad85 100644 --- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java +++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java @@ -30,7 +30,7 @@ import com.android.inputmethod.latin.R; import java.util.HashMap; -public class KeyCodeDescriptionMapper { +public final class KeyCodeDescriptionMapper { private static final String TAG = KeyCodeDescriptionMapper.class.getSimpleName(); // The resource ID of the string spoken for obscured keys diff --git a/java/src/com/android/inputmethod/compat/AudioManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/AudioManagerCompatWrapper.java index b6c3e2a88..40eed91f2 100644 --- a/java/src/com/android/inputmethod/compat/AudioManagerCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/AudioManagerCompatWrapper.java @@ -20,7 +20,7 @@ import android.media.AudioManager; import java.lang.reflect.Method; -public class AudioManagerCompatWrapper { +public final class AudioManagerCompatWrapper { private static final Method METHOD_isWiredHeadsetOn = CompatUtils.getMethod( AudioManager.class, "isWiredHeadsetOn"); private static final Method METHOD_isBluetoothA2dpOn = CompatUtils.getMethod( diff --git a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java index cc10a4ed2..a01c301ee 100644 --- a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java @@ -27,7 +27,7 @@ import java.lang.reflect.Method; // TODO: Override this class with the concrete implementation if we need to take care of the // performance. -public class InputMethodManagerCompatWrapper { +public final class InputMethodManagerCompatWrapper { private static final String TAG = InputMethodManagerCompatWrapper.class.getSimpleName(); private static final Method METHOD_switchToNextInputMethod = CompatUtils.getMethod( InputMethodManager.class, "switchToNextInputMethod", IBinder.class, Boolean.TYPE); diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index cb120a33e..30812e8c3 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -138,7 +138,7 @@ public class Key implements Comparable { private final OptionalAttributes mOptionalAttributes; - private static class OptionalAttributes { + private static final class OptionalAttributes { /** Text to output when pressed. This can be multiple characters, like ".com" */ public final String mOutputText; public final int mAltCode; diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java index 1e5277345..5e8a8f6bb 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java @@ -33,7 +33,7 @@ import java.util.Locale; /** * Unique identifier for each keyboard type. */ -public class KeyboardId { +public final class KeyboardId { public static final int MODE_TEXT = 0; public static final int MODE_URL = 1; public static final int MODE_EMAIL = 2; diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java index d97df7491..c7813ab02 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java @@ -61,7 +61,7 @@ import java.util.HashMap; * A {@link KeyboardLayoutSet} needs to be created for each * {@link android.view.inputmethod.EditorInfo}. */ -public class KeyboardLayoutSet { +public final class KeyboardLayoutSet { private static final String TAG = KeyboardLayoutSet.class.getSimpleName(); private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG; @@ -77,7 +77,7 @@ public class KeyboardLayoutSet { CollectionUtils.newHashMap(); private static final KeysCache sKeysCache = new KeysCache(); - public static class KeyboardLayoutSetException extends RuntimeException { + public static final class KeyboardLayoutSetException extends RuntimeException { public final KeyboardId mKeyboardId; public KeyboardLayoutSetException(final Throwable cause, final KeyboardId keyboardId) { @@ -86,13 +86,13 @@ public class KeyboardLayoutSet { } } - private static class ElementParams { + private static final class ElementParams { int mKeyboardXmlId; boolean mProximityCharsCorrectionEnabled; public ElementParams() {} } - private static class Params { + private static final class Params { String mKeyboardLayoutSetName; int mMode; EditorInfo mEditorInfo; @@ -203,7 +203,7 @@ public class KeyboardLayoutSet { params.mLanguageSwitchKeyEnabled); } - public static class Builder { + public static final class Builder { private final Context mContext; private final String mPackageName; private final Resources mResources; diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index fd789f029..88d7b667f 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -39,12 +39,12 @@ import com.android.inputmethod.latin.SettingsValues; import com.android.inputmethod.latin.SubtypeSwitcher; import com.android.inputmethod.latin.WordComposer; -public class KeyboardSwitcher implements KeyboardState.SwitchActions { +public final class KeyboardSwitcher implements KeyboardState.SwitchActions { private static final String TAG = KeyboardSwitcher.class.getSimpleName(); public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20110916"; - static class KeyboardTheme { + static final class KeyboardTheme { public final int mThemeId; public final int mStyleId; diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index f1fcfe785..b4c9c7d6f 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -83,7 +83,7 @@ import java.util.WeakHashMap; * @attr ref R.styleable#MainKeyboardView_ignoreAltCodeKeyTimeout * @attr ref R.styleable#MainKeyboardView_showMoreKeysKeyboardAtTouchPoint */ -public class MainKeyboardView extends KeyboardView implements PointerTracker.KeyEventHandler, +public final class MainKeyboardView extends KeyboardView implements PointerTracker.KeyEventHandler, SuddenJumpingTouchEventHandler.ProcessMotionEvent { private static final String TAG = MainKeyboardView.class.getSimpleName(); @@ -136,7 +136,7 @@ public class MainKeyboardView extends KeyboardView implements PointerTracker.Key private final KeyTimerHandler mKeyTimerHandler; - private static class KeyTimerHandler extends StaticInnerHandlerWrapper + private static final class KeyTimerHandler extends StaticInnerHandlerWrapper implements TimerProxy { private static final int MSG_TYPING_STATE_EXPIRED = 0; private static final int MSG_REPEAT_KEY = 1; diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java index cd4e3001e..a2001cb8f 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java @@ -16,7 +16,7 @@ package com.android.inputmethod.keyboard; -public class MoreKeysDetector extends KeyDetector { +public final class MoreKeysDetector extends KeyDetector { private final int mSlideAllowanceSquare; private final int mSlideAllowanceSquareTop; diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java index c9af888f9..d7d4be40b 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java @@ -27,7 +27,7 @@ import com.android.inputmethod.keyboard.internal.MoreKeySpec; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.StringUtils; -public class MoreKeysKeyboard extends Keyboard { +public final class MoreKeysKeyboard extends Keyboard { private final int mDefaultKeyCoordX; MoreKeysKeyboard(final MoreKeysKeyboardParams params) { diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java index e513a1477..a50617693 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java @@ -33,7 +33,7 @@ import com.android.inputmethod.latin.R; * A view that renders a virtual {@link MoreKeysKeyboard}. It handles rendering of keys and * detecting key presses and touch movements. */ -public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel { +public final class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel { private final int[] mCoordinates = new int[2]; private final KeyDetector mKeyDetector; diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index ec8f65994..9dae40a93 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -34,7 +34,7 @@ import com.android.inputmethod.research.ResearchLogger; import java.util.ArrayList; -public class PointerTracker implements PointerTrackerQueue.Element { +public final class PointerTracker implements PointerTrackerQueue.Element { private static final String TAG = PointerTracker.class.getSimpleName(); private static final boolean DEBUG_EVENT = false; private static final boolean DEBUG_MOVE_EVENT = false; @@ -121,7 +121,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { } } - static class PointerTrackerParams { + static final class PointerTrackerParams { public final boolean mSlidingKeyInputEnabled; public final int mTouchNoiseThresholdTime; public final float mTouchNoiseThresholdDistance; diff --git a/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java index 5712df1fc..44aa72a0a 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java @@ -18,7 +18,7 @@ package com.android.inputmethod.keyboard.internal; import android.util.Log; -public class AlphabetShiftState { +public final class AlphabetShiftState { private static final String TAG = AlphabetShiftState.class.getSimpleName(); private static final boolean DEBUG = false; diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java index 3487b5018..5b3f31805 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java +++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java @@ -16,7 +16,7 @@ package com.android.inputmethod.keyboard.internal; import com.android.inputmethod.latin.ResizableIntArray; -public class GestureStrokeWithPreviewPoints extends GestureStroke { +public final class GestureStrokeWithPreviewPoints extends GestureStroke { public static final int PREVIEW_CAPACITY = 256; private final ResizableIntArray mPreviewEventTimes = new ResizableIntArray(PREVIEW_CAPACITY); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java index 2a57caa5f..2caa5eb02 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java @@ -46,7 +46,7 @@ import java.util.Locale; * Note that the '\' is also parsed by XML parser and CSV parser as well. * See {@link KeyboardIconsSet} about icon_name. */ -public class KeySpecParser { +public final class KeySpecParser { private static final boolean DEBUG = LatinImeLogger.sDBG; private static final int MAX_STRING_REFERENCE_INDIRECTION = 10; @@ -318,7 +318,7 @@ public class KeySpecParser { } @SuppressWarnings("serial") - public static class KeySpecParserError extends RuntimeException { + public static final class KeySpecParserError extends RuntimeException { public KeySpecParserError(final String message) { super(message); } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java index 71fd30563..563d22414 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java @@ -29,7 +29,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.util.HashMap; -public class KeyStylesSet { +public final class KeyStylesSet { private static final String TAG = KeyStylesSet.class.getSimpleName(); private static final boolean DEBUG = false; @@ -45,7 +45,7 @@ public class KeyStylesSet { mStyles.put(EMPTY_STYLE_NAME, mEmptyKeyStyle); } - private static class EmptyKeyStyle extends KeyStyle { + private static final class EmptyKeyStyle extends KeyStyle { EmptyKeyStyle(final KeyboardTextsSet textsSet) { super(textsSet); } @@ -71,7 +71,7 @@ public class KeyStylesSet { } } - private static class DeclaredKeyStyle extends KeyStyle { + private static final class DeclaredKeyStyle extends KeyStyle { private final HashMap mStyles; private final String mParentStyleName; private final SparseArray mStyleAttributes = CollectionUtils.newSparseArray(); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java b/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java index 04cc152fe..6ddd2a6fb 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java @@ -23,7 +23,7 @@ import android.util.SparseIntArray; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.ResourceUtils; -public class KeyVisualAttributes { +public final class KeyVisualAttributes { public final Typeface mTypeface; public final float mLetterRatio; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java index f7923d0b9..840d7133d 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java @@ -21,7 +21,7 @@ import com.android.inputmethod.latin.CollectionUtils; import java.util.HashMap; -public class KeyboardCodesSet { +public final class KeyboardCodesSet { private static final HashMap sLanguageToCodesMap = CollectionUtils.newHashMap(); private static final HashMap sNameToIdMap = CollectionUtils.newHashMap(); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java index 4a98a3698..7292e8e19 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java @@ -27,7 +27,7 @@ import com.android.inputmethod.latin.R; import java.util.HashMap; -public class KeyboardIconsSet { +public final class KeyboardIconsSet { private static final String TAG = KeyboardIconsSet.class.getSimpleName(); public static final int ICON_UNDEFINED = 0; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardRow.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardRow.java index eb17b0ea4..b986262d7 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardRow.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardRow.java @@ -32,7 +32,7 @@ import org.xmlpull.v1.XmlPullParser; * Some of the key size defaults can be overridden per row from what the {@link Keyboard} * defines. */ -public class KeyboardRow { +public final class KeyboardRow { // keyWidth enum constants private static final int KEYWIDTH_NOT_ENUM = 0; private static final int KEYWIDTH_FILL_RIGHT = -1; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index 4ab6832c3..58cc8972a 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -34,7 +34,7 @@ import com.android.inputmethod.latin.Constants; * * The actions are {@link SwitchActions}'s methods. */ -public class KeyboardState { +public final class KeyboardState { private static final String TAG = KeyboardState.class.getSimpleName(); private static final boolean DEBUG_EVENT = false; private static final boolean DEBUG_ACTION = false; @@ -92,7 +92,7 @@ public class KeyboardState { private final SavedKeyboardState mSavedKeyboardState = new SavedKeyboardState(); - static class SavedKeyboardState { + static final class SavedKeyboardState { public boolean mIsValid; public boolean mIsAlphabetMode; public boolean mIsAlphabetShiftLocked; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeysCache.java b/java/src/com/android/inputmethod/keyboard/internal/KeysCache.java index f54617c98..d1b4c8524 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeysCache.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeysCache.java @@ -21,7 +21,7 @@ import com.android.inputmethod.latin.CollectionUtils; import java.util.HashMap; -public class KeysCache { +public final class KeysCache { private final HashMap mMap = CollectionUtils.newHashMap(); public void clear() { diff --git a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java index c1a5cbead..a52f202aa 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java +++ b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java @@ -22,7 +22,7 @@ import com.android.inputmethod.latin.CollectionUtils; import java.util.ArrayList; -public class PointerTrackerQueue { +public final class PointerTrackerQueue { private static final String TAG = PointerTrackerQueue.class.getSimpleName(); private static final boolean DEBUG = false; diff --git a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java index 72be7fc59..776ac0204 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java +++ b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java @@ -39,7 +39,7 @@ import com.android.inputmethod.latin.CollectionUtils; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.StaticInnerHandlerWrapper; -public class PreviewPlacerView extends RelativeLayout { +public final class PreviewPlacerView extends RelativeLayout { // The height of extra area above the keyboard to draw gesture trails. // Proportional to the keyboard height. private static final float EXTRA_GESTURE_TRAIL_AREA_ABOVE_KEYBOARD_RATIO = 0.25f; @@ -79,7 +79,7 @@ public class PreviewPlacerView extends RelativeLayout { private final DrawingHandler mDrawingHandler; - private static class DrawingHandler extends StaticInnerHandlerWrapper { + private static final class DrawingHandler extends StaticInnerHandlerWrapper { private static final int MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 0; private static final int MSG_UPDATE_GESTURE_PREVIEW_TRAIL = 1; diff --git a/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java b/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java index edb40c8e7..90db73dee 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java @@ -18,7 +18,7 @@ package com.android.inputmethod.keyboard.internal; import android.util.Log; -/* package */ class ShiftKeyState extends ModifierKeyState { +/* package */ final class ShiftKeyState extends ModifierKeyState { private static final int PRESSING_ON_SHIFTED = 3; // both temporary shifted & shift locked private static final int IGNORING = 4; diff --git a/java/src/com/android/inputmethod/keyboard/internal/SuddenJumpingTouchEventHandler.java b/java/src/com/android/inputmethod/keyboard/internal/SuddenJumpingTouchEventHandler.java index a591a7ac3..c53428fe5 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/SuddenJumpingTouchEventHandler.java +++ b/java/src/com/android/inputmethod/keyboard/internal/SuddenJumpingTouchEventHandler.java @@ -28,7 +28,7 @@ import com.android.inputmethod.latin.ResourceUtils; import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.research.ResearchLogger; -public class SuddenJumpingTouchEventHandler { +public final class SuddenJumpingTouchEventHandler { private static final String TAG = SuddenJumpingTouchEventHandler.class.getSimpleName(); private static boolean DEBUG_MODE = LatinImeLogger.sDBG; diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java index ae51d2537..d12607721 100644 --- a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java +++ b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java @@ -49,7 +49,7 @@ import com.android.inputmethod.compat.CompatUtils; import java.util.ArrayList; import java.util.TreeSet; -public class AdditionalSubtypeSettings extends PreferenceFragment { +public final class AdditionalSubtypeSettings extends PreferenceFragment { private SharedPreferences mPrefs; private SubtypeLocaleAdapter mSubtypeLocaleAdapter; private KeyboardLayoutSetAdapter mKeyboardLayoutSetAdapter; diff --git a/java/src/com/android/inputmethod/latin/AssetFileAddress.java b/java/src/com/android/inputmethod/latin/AssetFileAddress.java index 3549a1561..29c733ba6 100644 --- a/java/src/com/android/inputmethod/latin/AssetFileAddress.java +++ b/java/src/com/android/inputmethod/latin/AssetFileAddress.java @@ -24,7 +24,7 @@ import java.io.File; * the package file. Open it correctly thus requires the name of the package it is in, but * also the offset in the file and the length of this data. This class encapsulates these three. */ -class AssetFileAddress { +final class AssetFileAddress { public final String mFilename; public final long mOffset; public final long mLength; diff --git a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java index 55664d411..59ef5e09f 100644 --- a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java +++ b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java @@ -30,7 +30,7 @@ import com.android.inputmethod.latin.VibratorUtils; * It offers a consistent and simple interface that allows LatinIME to forget about the * complexity of settings and the like. */ -public class AudioAndHapticFeedbackManager { +public final class AudioAndHapticFeedbackManager { final private SettingsValues mSettingsValues; final private AudioManager mAudioManager; final private VibratorUtils mVibratorUtils; diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java index f425e360a..84fad158f 100644 --- a/java/src/com/android/inputmethod/latin/AutoCorrection.java +++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java @@ -23,7 +23,7 @@ import android.util.Log; import java.util.concurrent.ConcurrentHashMap; -public class AutoCorrection { +public final class AutoCorrection { private static final boolean DBG = LatinImeLogger.sDBG; private static final String TAG = AutoCorrection.class.getSimpleName(); private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4; diff --git a/java/src/com/android/inputmethod/latin/BackupAgent.java b/java/src/com/android/inputmethod/latin/BackupAgent.java index ee070af75..0beb088ac 100644 --- a/java/src/com/android/inputmethod/latin/BackupAgent.java +++ b/java/src/com/android/inputmethod/latin/BackupAgent.java @@ -22,7 +22,7 @@ import android.app.backup.SharedPreferencesBackupHelper; /** * Backs up the Latin IME shared preferences. */ -public class BackupAgent extends BackupAgentHelper { +public final class BackupAgent extends BackupAgentHelper { @Override public void onCreate() { diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 9244f16b1..e084cb306 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -30,7 +30,7 @@ import java.util.Locale; /** * Implements a static, compacted, binary dictionary of standard words. */ -public class BinaryDictionary extends Dictionary { +public final class BinaryDictionary extends Dictionary { public static final String DICTIONARY_PACK_AUTHORITY = "com.android.inputmethod.latin.dictionarypack"; diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index 799aea8ef..0b115945b 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -30,7 +30,6 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -40,7 +39,7 @@ import java.util.Locale; * Group class for static methods to help with creation and getting of the binary dictionary * file from the dictionary provider */ -public class BinaryDictionaryFileDumper { +public final class BinaryDictionaryFileDumper { private static final String TAG = BinaryDictionaryFileDumper.class.getSimpleName(); private static final boolean DEBUG = false; diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index 9764df072..fa9f79ecd 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -37,7 +37,7 @@ import java.util.Locale; /** * Helper class to get the address of a mmap'able dictionary file. */ -class BinaryDictionaryGetter { +final class BinaryDictionaryGetter { /** * Used for Log actions from this class @@ -178,7 +178,7 @@ class BinaryDictionaryGetter { context.getApplicationInfo().sourceDir, afd.getStartOffset(), afd.getLength()); } - static private class DictPackSettings { + private static final class DictPackSettings { final SharedPreferences mDictPreferences; public DictPackSettings(final Context context) { Context dictPackContext = null; @@ -237,7 +237,7 @@ class BinaryDictionaryGetter { /** * Utility class for the {@link #getCachedWordLists} method */ - private static class FileAndMatchLevel { + private static final class FileAndMatchLevel { final File mFile; final int mMatchLevel; public FileAndMatchLevel(final File file, final int matchLevel) { diff --git a/java/src/com/android/inputmethod/latin/BoundedTreeSet.java b/java/src/com/android/inputmethod/latin/BoundedTreeSet.java index cf977617d..7f7ff31c8 100644 --- a/java/src/com/android/inputmethod/latin/BoundedTreeSet.java +++ b/java/src/com/android/inputmethod/latin/BoundedTreeSet.java @@ -25,7 +25,7 @@ import java.util.TreeSet; /** * A TreeSet that is bounded in size and throws everything that's smaller than its limit */ -public class BoundedTreeSet extends TreeSet { +public final class BoundedTreeSet extends TreeSet { private final int mCapacity; public BoundedTreeSet(final Comparator comparator, final int capacity) { super(comparator); diff --git a/java/src/com/android/inputmethod/latin/DebugSettings.java b/java/src/com/android/inputmethod/latin/DebugSettings.java index 1ea14dad5..3af3cab2c 100644 --- a/java/src/com/android/inputmethod/latin/DebugSettings.java +++ b/java/src/com/android/inputmethod/latin/DebugSettings.java @@ -30,7 +30,7 @@ import android.util.Log; import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.research.ResearchLogger; -public class DebugSettings extends PreferenceFragment +public final class DebugSettings extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = DebugSettings.class.getSimpleName(); diff --git a/java/src/com/android/inputmethod/latin/DebugSettingsActivity.java b/java/src/com/android/inputmethod/latin/DebugSettingsActivity.java index cde20606a..6ef19ee82 100644 --- a/java/src/com/android/inputmethod/latin/DebugSettingsActivity.java +++ b/java/src/com/android/inputmethod/latin/DebugSettingsActivity.java @@ -20,7 +20,7 @@ import android.content.Intent; import android.os.Bundle; import android.preference.PreferenceActivity; -public class DebugSettingsActivity extends PreferenceActivity { +public final class DebugSettingsActivity extends PreferenceActivity { @Override public Intent getIntent() { final Intent modIntent = new Intent(super.getIntent()); diff --git a/java/src/com/android/inputmethod/latin/DicTraverseSession.java b/java/src/com/android/inputmethod/latin/DicTraverseSession.java index 359da72cc..ce1b64660 100644 --- a/java/src/com/android/inputmethod/latin/DicTraverseSession.java +++ b/java/src/com/android/inputmethod/latin/DicTraverseSession.java @@ -18,7 +18,7 @@ package com.android.inputmethod.latin; import java.util.Locale; -public class DicTraverseSession { +public final class DicTraverseSession { static { JniUtils.loadNativeLibrary(); } diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java index 4acab6b05..d3b120989 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java +++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java @@ -29,7 +29,7 @@ import java.util.concurrent.CopyOnWriteArrayList; /** * Class for a collection of dictionaries that behave like one dictionary. */ -public class DictionaryCollection extends Dictionary { +public final class DictionaryCollection extends Dictionary { private final String TAG = DictionaryCollection.class.getSimpleName(); protected final CopyOnWriteArrayList mDictionaries; diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index cdd01d0c7..f381973ae 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -29,7 +29,7 @@ import java.util.Locale; /** * Factory for dictionary instances. */ -public class DictionaryFactory { +public final class DictionaryFactory { private static final String TAG = DictionaryFactory.class.getSimpleName(); // This class must be located in the same package as LatinIME.java. private static final String RESOURCE_PACKAGE_NAME = diff --git a/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java b/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java index 9c37d7673..f2f3fbded 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java +++ b/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java @@ -27,7 +27,7 @@ import android.net.Uri; /** * Takes action to reload the necessary data when a dictionary pack was added/removed. */ -public class DictionaryPackInstallBroadcastReceiver extends BroadcastReceiver { +public final class DictionaryPackInstallBroadcastReceiver extends BroadcastReceiver { final LatinIME mService; /** diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java index 8a38d1e1b..8cdc2a0af 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -48,7 +48,7 @@ public class ExpandableDictionary extends Dictionary { // Use this lock before touching mUpdatingDictionary & mRequiresDownload private Object mUpdatingLock = new Object(); - private static class Node { + private static final class Node { Node() {} char mCode; int mFrequency; @@ -60,7 +60,7 @@ public class ExpandableDictionary extends Dictionary { LinkedList mNGrams; // Supports ngram } - private static class NodeArray { + private static final class NodeArray { Node[] mData; int mLength = 0; private static final int INCREMENT = 2; @@ -88,7 +88,7 @@ public class ExpandableDictionary extends Dictionary { public int notifyTypedAgainAndGetFrequency(); } - private static class NextStaticWord implements NextWord { + private static final class NextStaticWord implements NextWord { public final Node mWord; private final int mFrequency; public NextStaticWord(Node word, int frequency) { @@ -117,7 +117,7 @@ public class ExpandableDictionary extends Dictionary { } } - private static class NextHistoryWord implements NextWord { + private static final class NextHistoryWord implements NextWord { public final Node mWord; public final ForgettingCurveParams mFcp; @@ -703,7 +703,7 @@ public class ExpandableDictionary extends Dictionary { mRoots = new NodeArray(); } - private class LoadDictionaryTask extends Thread { + private final class LoadDictionaryTask extends Thread { LoadDictionaryTask() {} @Override public void run() { diff --git a/java/src/com/android/inputmethod/latin/FileTransforms.java b/java/src/com/android/inputmethod/latin/FileTransforms.java index 80159521c..09cf23a9b 100644 --- a/java/src/com/android/inputmethod/latin/FileTransforms.java +++ b/java/src/com/android/inputmethod/latin/FileTransforms.java @@ -21,7 +21,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.zip.GZIPInputStream; -public class FileTransforms { +public final class FileTransforms { public static OutputStream getCryptedStream(OutputStream out) { // Crypt the stream. return out; diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java index 7bcda9bc4..2f7608a03 100644 --- a/java/src/com/android/inputmethod/latin/InputAttributes.java +++ b/java/src/com/android/inputmethod/latin/InputAttributes.java @@ -23,7 +23,7 @@ import android.view.inputmethod.EditorInfo; /** * Class to hold attributes of the input field. */ -public class InputAttributes { +public final class InputAttributes { private final String TAG = InputAttributes.class.getSimpleName(); final public boolean mInputTypeNoAutoCorrect; diff --git a/java/src/com/android/inputmethod/latin/InputPointers.java b/java/src/com/android/inputmethod/latin/InputPointers.java index ff2feb51d..6b48aabb3 100644 --- a/java/src/com/android/inputmethod/latin/InputPointers.java +++ b/java/src/com/android/inputmethod/latin/InputPointers.java @@ -17,7 +17,7 @@ package com.android.inputmethod.latin; // TODO: This class is not thread-safe. -public class InputPointers { +public final class InputPointers { private final int mDefaultCapacity; private final ResizableIntArray mXCoordinates; private final ResizableIntArray mYCoordinates; diff --git a/java/src/com/android/inputmethod/latin/InputView.java b/java/src/com/android/inputmethod/latin/InputView.java index c15f45345..d7595bfbe 100644 --- a/java/src/com/android/inputmethod/latin/InputView.java +++ b/java/src/com/android/inputmethod/latin/InputView.java @@ -23,7 +23,7 @@ import android.view.MotionEvent; import android.view.View; import android.widget.LinearLayout; -public class InputView extends LinearLayout { +public final class InputView extends LinearLayout { private View mSuggestionStripContainer; private View mKeyboardView; private int mKeyboardTopPadding; diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java index dd73a978c..94cdc9b85 100644 --- a/java/src/com/android/inputmethod/latin/LastComposedWord.java +++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java @@ -22,7 +22,7 @@ import android.text.TextUtils; * This class encapsulates data about a word previously composed, but that has been * committed already. This is used for resuming suggestion, and cancel auto-correction. */ -public class LastComposedWord { +public final class LastComposedWord { // COMMIT_TYPE_USER_TYPED_WORD is used when the word committed is the exact typed word, with // no hinting from the IME. It happens when some external event happens (rotating the device, // for example) or when auto-correction is off by settings or editor attributes. diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index b8a8f9aaf..3e893303f 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -85,7 +85,7 @@ import java.util.Locale; /** * Input method implementation for Qwerty'ish keyboard. */ -public class LatinIME extends InputMethodService implements KeyboardActionListener, +public final class LatinIME extends InputMethodService implements KeyboardActionListener, SuggestionStripView.Listener, TargetApplicationGetter.OnTargetApplicationKnownListener, Suggest.SuggestInitializationListener { private static final String TAG = LatinIME.class.getSimpleName(); @@ -183,7 +183,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen public final UIHandler mHandler = new UIHandler(this); - public static class UIHandler extends StaticInnerHandlerWrapper { + public static final class UIHandler extends StaticInnerHandlerWrapper { private static final int MSG_UPDATE_SHIFT_STATE = 0; private static final int MSG_PENDING_IMS_CALLBACK = 1; private static final int MSG_UPDATE_SUGGESTION_STRIP = 2; diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java index 9eab19c49..394a9c7aa 100644 --- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java +++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java @@ -21,7 +21,7 @@ import android.view.inputmethod.EditorInfo; import com.android.inputmethod.keyboard.Keyboard; -public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChangeListener { +public final class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChangeListener { public static boolean sDBG = false; public static boolean sVISUALDEBUG = false; diff --git a/java/src/com/android/inputmethod/latin/ResizableIntArray.java b/java/src/com/android/inputmethod/latin/ResizableIntArray.java index c660f92c4..9a46f160b 100644 --- a/java/src/com/android/inputmethod/latin/ResizableIntArray.java +++ b/java/src/com/android/inputmethod/latin/ResizableIntArray.java @@ -19,7 +19,7 @@ package com.android.inputmethod.latin; import java.util.Arrays; // TODO: This class is not thread-safe. -public class ResizableIntArray { +public final class ResizableIntArray { private int[] mArray; private int mLength; diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index 28c0c0f16..1acca5860 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -41,7 +41,7 @@ import java.util.regex.Pattern; * all the time to find out what text is in the buffer, when we need it to determine caps mode * for example. */ -public class RichInputConnection { +public final class RichInputConnection { private static final String TAG = RichInputConnection.class.getSimpleName(); private static final boolean DBG = false; private static final boolean DEBUG_PREVIOUS_TEXT = false; @@ -415,7 +415,7 @@ public class RichInputConnection { /** * Represents a range of text, relative to the current cursor position. */ - public static class Range { + public static final class Range { /** Characters before selection start */ public final int mCharsBefore; diff --git a/java/src/com/android/inputmethod/latin/SettingsActivity.java b/java/src/com/android/inputmethod/latin/SettingsActivity.java index 68f8582fc..0d3c8ebb7 100644 --- a/java/src/com/android/inputmethod/latin/SettingsActivity.java +++ b/java/src/com/android/inputmethod/latin/SettingsActivity.java @@ -19,7 +19,7 @@ package com.android.inputmethod.latin; import android.content.Intent; import android.preference.PreferenceActivity; -public class SettingsActivity extends PreferenceActivity { +public final class SettingsActivity extends PreferenceActivity { private static final String DEFAULT_FRAGMENT = Settings.class.getName(); @Override diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java index de5f515b0..579f96bb4 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java +++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java @@ -30,7 +30,7 @@ import com.android.inputmethod.latin.LocaleUtils.RunInLocale; import java.util.HashMap; import java.util.Locale; -public class SubtypeLocale { +public final class SubtypeLocale { static final String TAG = SubtypeLocale.class.getSimpleName(); // This class must be located in the same package as LatinIME.java. private static final String RESOURCE_PACKAGE_NAME = diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index c693edcca..8e51a372b 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -38,7 +38,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; -public class SubtypeSwitcher { +public final class SubtypeSwitcher { private static boolean DBG = LatinImeLogger.sDBG; private static final String TAG = SubtypeSwitcher.class.getSimpleName(); @@ -60,7 +60,7 @@ public class SubtypeSwitcher { private boolean mIsNetworkConnected; - static class NeedsToDisplayLanguage { + static final class NeedsToDisplayLanguage { private int mEnabledSubtypeCount; private boolean mIsSystemLanguageSameAsInputLanguage; diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 278c4b9ce..f0e3b4ebd 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -34,7 +34,7 @@ import java.util.concurrent.ConcurrentHashMap; * This class loads a dictionary and provides a list of suggestions for a given sequence of * characters. This includes corrections and completions. */ -public class Suggest { +public final class Suggest { public static final String TAG = Suggest.class.getSimpleName(); // Session id for @@ -362,7 +362,8 @@ public class Suggest { return suggestionsList; } - private static class SuggestedWordInfoComparator implements Comparator { + private static final class SuggestedWordInfoComparator + implements Comparator { // This comparator ranks the word info with the higher frequency first. That's because // that's the order we want our elements in. @Override diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index d9f48c4a4..52e292a86 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -23,7 +23,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; -public class SuggestedWords { +public final class SuggestedWords { private static final ArrayList EMPTY_WORD_INFO_LIST = CollectionUtils.newArrayList(0); public static final SuggestedWords EMPTY = new SuggestedWords( @@ -117,7 +117,7 @@ public class SuggestedWords { return suggestionsList; } - public static class SuggestedWordInfo { + public static final class SuggestedWordInfo { public static final int MAX_SCORE = Integer.MAX_VALUE; public static final int KIND_TYPED = 0; // What user typed public static final int KIND_CORRECTION = 1; // Simple correction/suggestion diff --git a/java/src/com/android/inputmethod/latin/SuggestionSpanPickedNotificationReceiver.java b/java/src/com/android/inputmethod/latin/SuggestionSpanPickedNotificationReceiver.java index 4a3f42d5d..d188fc5ef 100644 --- a/java/src/com/android/inputmethod/latin/SuggestionSpanPickedNotificationReceiver.java +++ b/java/src/com/android/inputmethod/latin/SuggestionSpanPickedNotificationReceiver.java @@ -23,7 +23,7 @@ import android.content.Context; import android.content.Intent; import android.util.Log; -public class SuggestionSpanPickedNotificationReceiver extends BroadcastReceiver { +public final class SuggestionSpanPickedNotificationReceiver extends BroadcastReceiver { private static final boolean DBG = LatinImeLogger.sDBG; private static final String TAG = SuggestionSpanPickedNotificationReceiver.class.getSimpleName(); diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java index bdd988df2..8f21b7b4a 100644 --- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java @@ -24,7 +24,7 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import java.util.ArrayList; import java.util.Locale; -public class SynchronouslyLoadedContactsBinaryDictionary extends ContactsBinaryDictionary { +public final class SynchronouslyLoadedContactsBinaryDictionary extends ContactsBinaryDictionary { private boolean mClosed; public SynchronouslyLoadedContactsBinaryDictionary(final Context context, final Locale locale) { diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java index b8cfddd4e..612f54d73 100644 --- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java @@ -23,7 +23,7 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import java.util.ArrayList; -public class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDictionary { +public final class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDictionary { public SynchronouslyLoadedUserBinaryDictionary(final Context context, final String locale) { this(context, locale, false); diff --git a/java/src/com/android/inputmethod/latin/TargetApplicationGetter.java b/java/src/com/android/inputmethod/latin/TargetApplicationGetter.java index 4265309e5..743a8c60f 100644 --- a/java/src/com/android/inputmethod/latin/TargetApplicationGetter.java +++ b/java/src/com/android/inputmethod/latin/TargetApplicationGetter.java @@ -22,8 +22,7 @@ import android.content.pm.PackageManager; import android.os.AsyncTask; import android.util.LruCache; -public class TargetApplicationGetter extends AsyncTask { - +public final class TargetApplicationGetter extends AsyncTask { private static final int MAX_CACHE_ENTRIES = 64; // arbitrary private static LruCache sCache = new LruCache(MAX_CACHE_ENTRIES); @@ -32,6 +31,7 @@ public class TargetApplicationGetter extends AsyncTask + private static final class UpdateBinaryTask extends AsyncTask implements BigramDictionaryInterface { private final UserHistoryDictionaryBigramList mBigramList; private final boolean mAddLevel0Bigrams; diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java index bb0f5429a..df44948f9 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java @@ -26,7 +26,7 @@ import java.util.Set; * All bigrams including stale ones in SQL DB should be stored in this class to avoid adding stale * bigrams when we write to the SQL DB. */ -public class UserHistoryDictionaryBigramList { +public final class UserHistoryDictionaryBigramList { public static final byte FORGETTING_CURVE_INITIAL_VALUE = 0; private static final String TAG = UserHistoryDictionaryBigramList.class.getSimpleName(); private static final HashMap EMPTY_BIGRAM_MAP = CollectionUtils.newHashMap(); diff --git a/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java b/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java index 3d3bd980c..9053d709b 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java @@ -36,7 +36,7 @@ public final class UserHistoryForgettingCurveUtils { // This utility class is not publicly instantiable. } - public static class ForgettingCurveParams { + public static final class ForgettingCurveParams { private byte mFc; long mLastTouchedTime = 0; private final boolean mIsValid; @@ -195,7 +195,7 @@ public final class UserHistoryForgettingCurveUtils { return (elapsedTime < ELAPSED_TIME_MAX - 1 || level > 0); } - private static class MathUtils { + private static final class MathUtils { public static final int[][] SCORE_TABLE = new int[FC_LEVEL_MAX][ELAPSED_TIME_MAX + 1]; static { for (int i = 0; i < FC_LEVEL_MAX; ++i) { diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index 275ebf305..8a1bbed12 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -24,7 +24,7 @@ import java.util.Arrays; /** * A place to store the currently composing word with information such as adjacent key codes as well */ -public class WordComposer { +public final class WordComposer { private static final int N = BinaryDictionary.MAX_WORD_LENGTH; public static final int CAPS_MODE_OFF = 0; diff --git a/java/src/com/android/inputmethod/latin/WordListInfo.java b/java/src/com/android/inputmethod/latin/WordListInfo.java index 54f04d78f..095320e25 100644 --- a/java/src/com/android/inputmethod/latin/WordListInfo.java +++ b/java/src/com/android/inputmethod/latin/WordListInfo.java @@ -19,7 +19,7 @@ package com.android.inputmethod.latin; /** * Information container for a word list. */ -public class WordListInfo { +public final class WordListInfo { public final String mId; public final String mLocale; public WordListInfo(final String id, final String locale) { diff --git a/java/src/com/android/inputmethod/latin/XmlParseUtils.java b/java/src/com/android/inputmethod/latin/XmlParseUtils.java index b5cbaf19e..75dc68f1d 100644 --- a/java/src/com/android/inputmethod/latin/XmlParseUtils.java +++ b/java/src/com/android/inputmethod/latin/XmlParseUtils.java @@ -36,28 +36,28 @@ public final class XmlParseUtils { } @SuppressWarnings("serial") - public static class IllegalStartTag extends ParseException { + public static final class IllegalStartTag extends ParseException { public IllegalStartTag(XmlPullParser parser, String parent) { super("Illegal start tag " + parser.getName() + " in " + parent, parser); } } @SuppressWarnings("serial") - public static class IllegalEndTag extends ParseException { + public static final class IllegalEndTag extends ParseException { public IllegalEndTag(XmlPullParser parser, String parent) { super("Illegal end tag " + parser.getName() + " in " + parent, parser); } } @SuppressWarnings("serial") - public static class IllegalAttribute extends ParseException { + public static final class IllegalAttribute extends ParseException { public IllegalAttribute(XmlPullParser parser, String attribute) { super("Tag " + parser.getName() + " has illegal attribute " + attribute, parser); } } @SuppressWarnings("serial") - public static class NonEmptyTag extends ParseException{ + public static final class NonEmptyTag extends ParseException{ public NonEmptyTag(String tag, XmlPullParser parser) { super(tag + " must be empty tag", parser); } diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index a1606db60..7b0231a6b 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -27,10 +27,10 @@ import java.util.ArrayList; import java.util.Map; import java.util.Stack; -public class BinaryDictIOUtils { +public final class BinaryDictIOUtils { private static final boolean DBG = false; - private static class Position { + private static final class Position { public static final int NOT_READ_GROUPCOUNT = -1; public int mAddress; diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 9fc694218..b431a4da9 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -43,7 +43,7 @@ import java.util.TreeMap; * * All the methods in this class are static. */ -public class BinaryDictInputOutput { +public final class BinaryDictInputOutput { private static final boolean DBG = MakedictLog.DBG; @@ -124,7 +124,7 @@ public class BinaryDictInputOutput { /** * A class grouping utility function for our specific character encoding. */ - private static class CharEncoding { + private static final class CharEncoding { private static final int MINIMAL_ONE_BYTE_CHARACTER_VALUE = 0x20; private static final int MAXIMAL_ONE_BYTE_CHARACTER_VALUE = 0xFF; diff --git a/java/src/com/android/inputmethod/latin/makedict/CharGroupInfo.java b/java/src/com/android/inputmethod/latin/makedict/CharGroupInfo.java index ed9388409..8e64082e6 100644 --- a/java/src/com/android/inputmethod/latin/makedict/CharGroupInfo.java +++ b/java/src/com/android/inputmethod/latin/makedict/CharGroupInfo.java @@ -23,7 +23,7 @@ import java.util.ArrayList; /** * Raw char group info straight out of a file. This will contain numbers for addresses. */ -public class CharGroupInfo { +public final class CharGroupInfo { public final int mOriginalAddress; public final int mEndAddress; diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index 35311f0c2..b3fbb9fb5 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -221,7 +221,7 @@ public final class FormatSpec { /** * Options about file format. */ - public static class FormatOptions { + public static final class FormatOptions { public final int mVersion; public final boolean mSupportsDynamicUpdate; public FormatOptions(final int version) { diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java index 98cf308c8..3193ef457 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java +++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java @@ -28,8 +28,7 @@ import java.util.LinkedList; /** * A dictionary that can fusion heads and tails of words for more compression. */ -public class FusionDictionary implements Iterable { - +public final class FusionDictionary implements Iterable { private static final boolean DBG = MakedictLog.DBG; /** @@ -40,7 +39,7 @@ public class FusionDictionary implements Iterable { * This class also contains fields to cache size and address, to help with binary * generation. */ - public static class Node { + public static final class Node { ArrayList mData; // To help with binary generation int mCachedSize = Integer.MIN_VALUE; @@ -60,7 +59,7 @@ public class FusionDictionary implements Iterable { * * This represents an "attribute", that is either a bigram or a shortcut. */ - public static class WeightedString { + public static final class WeightedString { public final String mWord; public int mFrequency; public WeightedString(String word, int frequency) { @@ -94,7 +93,7 @@ public class FusionDictionary implements Iterable { * value is the frequency of this terminal. A terminal may have non-null shortcuts and/or * bigrams, but a non-terminal may not. Moreover, children, if present, are null. */ - public static class CharGroup { + public static final class CharGroup { public static final int NOT_A_TERMINAL = -1; final int mChars[]; ArrayList mShortcutTargets; @@ -253,7 +252,7 @@ public class FusionDictionary implements Iterable { * * There are no options at the moment, so this class is empty. */ - public static class DictionaryOptions { + public static final class DictionaryOptions { public final boolean mGermanUmlautProcessing; public final boolean mFrenchLigatureProcessing; public final HashMap mAttributes; @@ -511,7 +510,7 @@ public class FusionDictionary implements Iterable { * is ignored. * This comparator imposes orderings that are inconsistent with equals. */ - static private class CharGroupComparator implements java.util.Comparator { + static private final class CharGroupComparator implements java.util.Comparator { @Override public int compare(CharGroup c1, CharGroup c2) { if (c1.mChars[0] == c2.mChars[0]) return 0; @@ -746,9 +745,8 @@ public class FusionDictionary implements Iterable { * * This is purely for convenience. */ - public static class DictionaryIterator implements Iterator { - - private static class Position { + public static final class DictionaryIterator implements Iterator { + private static final class Position { public Iterator pos; public int length; public Position(ArrayList groups) { diff --git a/java/src/com/android/inputmethod/latin/makedict/MakedictLog.java b/java/src/com/android/inputmethod/latin/makedict/MakedictLog.java index 3f0cd0796..6c6b00b6a 100644 --- a/java/src/com/android/inputmethod/latin/makedict/MakedictLog.java +++ b/java/src/com/android/inputmethod/latin/makedict/MakedictLog.java @@ -21,7 +21,7 @@ import android.util.Log; /** * Wrapper to redirect log events to the right output medium. */ -public class MakedictLog { +public final class MakedictLog { public static final boolean DBG = false; private static final String TAG = MakedictLog.class.getSimpleName(); diff --git a/java/src/com/android/inputmethod/latin/makedict/PendingAttribute.java b/java/src/com/android/inputmethod/latin/makedict/PendingAttribute.java index 5b41d27f2..5bb24da74 100644 --- a/java/src/com/android/inputmethod/latin/makedict/PendingAttribute.java +++ b/java/src/com/android/inputmethod/latin/makedict/PendingAttribute.java @@ -22,7 +22,7 @@ package com.android.inputmethod.latin.makedict; * An attribute is either a bigram or a shortcut. * All instances of this class are always immutable. */ -public class PendingAttribute { +public final class PendingAttribute { public final int mFrequency; public final int mAddress; public PendingAttribute(final int frequency, final int address) { diff --git a/java/src/com/android/inputmethod/latin/makedict/UnsupportedFormatException.java b/java/src/com/android/inputmethod/latin/makedict/UnsupportedFormatException.java index bd42fb8fa..dbb2ea870 100644 --- a/java/src/com/android/inputmethod/latin/makedict/UnsupportedFormatException.java +++ b/java/src/com/android/inputmethod/latin/makedict/UnsupportedFormatException.java @@ -19,7 +19,7 @@ package com.android.inputmethod.latin.makedict; /** * Simple exception thrown when a file format is not recognized. */ -public class UnsupportedFormatException extends Exception { +public final class UnsupportedFormatException extends Exception { public UnsupportedFormatException(String description) { super(description); } diff --git a/java/src/com/android/inputmethod/latin/makedict/Word.java b/java/src/com/android/inputmethod/latin/makedict/Word.java index 4683ef154..4c4f18f1a 100644 --- a/java/src/com/android/inputmethod/latin/makedict/Word.java +++ b/java/src/com/android/inputmethod/latin/makedict/Word.java @@ -26,7 +26,7 @@ import java.util.Arrays; * * This is chiefly used to iterate a dictionary. */ -public class Word implements Comparable { +public final class Word implements Comparable { public final String mWord; public final int mFrequency; public final ArrayList mShortcutTargets; diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index eef7a51f2..5a11ae534 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -50,7 +50,7 @@ import java.util.TreeMap; /** * Service for spell checking, using LatinIME's dictionaries and mechanisms. */ -public class AndroidSpellCheckerService extends SpellCheckerService +public final class AndroidSpellCheckerService extends SpellCheckerService implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = AndroidSpellCheckerService.class.getSimpleName(); private static final boolean DBG = false; @@ -201,8 +201,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService } // TODO: remove this class and replace it by storage local to the session. - public static class SuggestionsGatherer { - public static class Result { + public static final class SuggestionsGatherer { + public static final class Result { public final String[] mSuggestions; public final boolean mHasRecommendedSuggestions; public Result(final String[] gatheredSuggestions, diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java index 5a1bd37f5..668e7a641 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java @@ -26,7 +26,7 @@ import com.android.inputmethod.latin.CollectionUtils; import java.util.ArrayList; -public class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheckerSession { +public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheckerSession { private static final String TAG = AndroidSpellCheckerSession.class.getSimpleName(); private static final boolean DBG = false; private final static String[] EMPTY_STRING_ARRAY = new String[0]; diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java index d9b622a18..53ed4d3c3 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java @@ -50,7 +50,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { protected final SuggestionsCache mSuggestionsCache = new SuggestionsCache(); private final ContentObserver mObserver; - private static class SuggestionsParams { + private static final class SuggestionsParams { public final String[] mSuggestions; public final int mFlags; public SuggestionsParams(String[] suggestions, int flags) { @@ -59,7 +59,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { } } - protected static class SuggestionsCache { + protected static final class SuggestionsCache { private static final char CHAR_DELIMITER = '\uFFFC'; private static final int MAX_CACHE_SIZE = 50; private final LruCache mUnigramSuggestionsInfoCache = diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictAndProximity.java b/java/src/com/android/inputmethod/latin/spellcheck/DictAndProximity.java index 3dbbd40cd..9d7c61a33 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/DictAndProximity.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/DictAndProximity.java @@ -22,7 +22,7 @@ import com.android.inputmethod.keyboard.ProximityInfo; /** * A simple container for both a Dictionary and a ProximityInfo. */ -public class DictAndProximity { +public final class DictAndProximity { public final Dictionary mDictionary; public final ProximityInfo mProximityInfo; public DictAndProximity(final Dictionary dictionary, final ProximityInfo proximityInfo) { diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java index 53aa6c719..1fb2bbb6a 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java @@ -36,7 +36,7 @@ import java.util.concurrent.TimeUnit; * the client code, but may help with sloppy clients. */ @SuppressWarnings("serial") -public class DictionaryPool extends LinkedBlockingQueue { +public final class DictionaryPool extends LinkedBlockingQueue { private final static String TAG = DictionaryPool.class.getSimpleName(); // How many seconds we wait for a dictionary to become available. Past this delay, we give up in // fear some bug caused a deadlock, and reset the whole pool. diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java index fe5225ebd..11bb97031 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java @@ -22,7 +22,7 @@ import com.android.inputmethod.latin.Constants; import java.util.TreeMap; -public class SpellCheckerProximityInfo { +public final class SpellCheckerProximityInfo { /* public for test */ final public static int NUL = Constants.NOT_A_CODE; @@ -53,7 +53,7 @@ public class SpellCheckerProximityInfo { return result; } - private static class Latin { + private static final class Latin { // This is a map from the code point to the index in the PROXIMITY array. // At the time the native code to read the binary dictionary needs the proximity info be // passed as a flat array spaced by MAX_PROXIMITY_CHARS_SIZE columns, one for each input @@ -122,7 +122,7 @@ public class SpellCheckerProximityInfo { } } - private static class Cyrillic { + private static final class Cyrillic { final private static TreeMap INDICES = CollectionUtils.newTreeMap(); // TODO: The following table is solely based on the keyboard layout. Consult with Russian // speakers on commonly misspelled words/letters. diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java index e14db8797..e63dff312 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java @@ -23,7 +23,7 @@ import android.preference.PreferenceActivity; /** * Spell checker preference screen. */ -public class SpellCheckerSettingsActivity extends PreferenceActivity { +public final class SpellCheckerSettingsActivity extends PreferenceActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java index 7056874a1..ef5123d68 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java @@ -24,7 +24,7 @@ import com.android.inputmethod.latin.R; /** * Preference screen. */ -public class SpellCheckerSettingsFragment extends PreferenceFragment { +public final class SpellCheckerSettingsFragment extends PreferenceFragment { /** * Empty constructor for fragment generation. */ diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java index 1f883aa60..e9bf0fac4 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java @@ -30,14 +30,14 @@ import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.Utils; -public class MoreSuggestions extends Keyboard { +public final class MoreSuggestions extends Keyboard { public static final int SUGGESTION_CODE_BASE = 1024; MoreSuggestions(final MoreSuggestionsParam params) { super(params); } - private static class MoreSuggestionsParam extends KeyboardParams { + private static final class MoreSuggestionsParam extends KeyboardParams { private final int[] mWidths = new int[SuggestionStripView.MAX_SUGGESTIONS]; private final int[] mRowNumbers = new int[SuggestionStripView.MAX_SUGGESTIONS]; private final int[] mColumnOrders = new int[SuggestionStripView.MAX_SUGGESTIONS]; @@ -163,7 +163,7 @@ public class MoreSuggestions extends Keyboard { } } - public static class Builder extends KeyboardBuilder { + public static final class Builder extends KeyboardBuilder { private final MoreSuggestionsView mPaneView; private SuggestedWords mSuggestions; private int mFromPos; @@ -216,7 +216,7 @@ public class MoreSuggestions extends Keyboard { } } - private static class Divider extends Key.Spacer { + private static final class Divider extends Key.Spacer { private final Drawable mIcon; public Divider(final KeyboardParams params, final Drawable icon, final int x, diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java index 5b23d7f3c..9b9a35478 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java @@ -40,7 +40,7 @@ import com.android.inputmethod.latin.R; * A view that renders a virtual {@link MoreSuggestions}. It handles rendering of keys and detecting * key presses and touch movements. */ -public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel { +public final class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel { private final int[] mCoordinates = new int[2]; final KeyDetector mModalPanelKeyDetector; diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index 9e8ab81b0..e926fa209 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -70,7 +70,7 @@ import com.android.inputmethod.research.ResearchLogger; import java.util.ArrayList; -public class SuggestionStripView extends RelativeLayout implements OnClickListener, +public final class SuggestionStripView extends RelativeLayout implements OnClickListener, OnLongClickListener { public interface Listener { public boolean addWordToUserDictionary(String word); @@ -105,7 +105,7 @@ public class SuggestionStripView extends RelativeLayout implements OnClickListen private final UiHandler mHandler = new UiHandler(this); - private static class UiHandler extends StaticInnerHandlerWrapper { + private static final class UiHandler extends StaticInnerHandlerWrapper { private static final int MSG_HIDE_PREVIEW = 0; public UiHandler(SuggestionStripView outerInstance) { @@ -131,7 +131,7 @@ public class SuggestionStripView extends RelativeLayout implements OnClickListen } } - private static class SuggestionStripViewParams { + private static final class SuggestionStripViewParams { private static final int DEFAULT_SUGGESTIONS_COUNT_IN_STRIP = 3; private static final float DEFAULT_CENTER_SUGGESTION_PERCENTILE = 0.40f; private static final int DEFAULT_MAX_MORE_SUGGESTIONS_ROW = 2; -- cgit v1.2.3-83-g751a From 7a7d117aa7e7157ed429d68c4797218476151d8d Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Fri, 28 Sep 2012 14:14:31 +0900 Subject: Ignore the broken file. bug: 7249561 Change-Id: If001bf75ef12b4d342a77e54706c7fed90c89afb --- java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java index 2cb29d310..e39011145 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java @@ -180,12 +180,14 @@ public final class UserHistoryDictIOUtils { try { BinaryDictIOUtils.readUnigramsAndBigramsBinary(buffer, unigrams, frequencies, bigrams); - addWordsFromWordMap(unigrams, frequencies, bigrams, dict); } catch (IOException e) { Log.e(TAG, "IO exception while reading file: " + e); } catch (UnsupportedFormatException e) { Log.e(TAG, "Unsupported format: " + e); + } catch (ArrayIndexOutOfBoundsException e) { + Log.e(TAG, "ArrayIndexOutOfBoundsException while reading file: " + e); } + addWordsFromWordMap(unigrams, frequencies, bigrams, dict); } /** -- cgit v1.2.3-83-g751a From f3aed3ea26b49cdf54e0b69c707ebd092ac45f97 Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Fri, 28 Sep 2012 16:47:33 +0900 Subject: Add updateChildrenAddress. Change-Id: Ic06a755d85612476e719e580469dc1cd9447286c --- .../latin/makedict/BinaryDictIOUtils.java | 36 ++++++++++++++++++++++ .../latin/makedict/BinaryDictInputOutput.java | 7 ++--- 2 files changed, 39 insertions(+), 4 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 7b0231a6b..c34d19d22 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -17,6 +17,7 @@ package com.android.inputmethod.latin.makedict; import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.CharEncoding; import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.FusionDictionaryBufferInterface; import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader; import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions; @@ -279,4 +280,39 @@ public final class BinaryDictIOUtils { putSInt24(buffer, parentOffset); buffer.position(originalPosition); } + + private static void skipString(final FusionDictionaryBufferInterface buffer, + final boolean hasMultipleChars) { + if (hasMultipleChars) { + int character = CharEncoding.readChar(buffer); + while (character != FormatSpec.INVALID_CHARACTER) { + character = CharEncoding.readChar(buffer); + } + } else { + CharEncoding.readChar(buffer); + } + } + + /** + * Update a children address in a CharGroup that is addressed by groupOriginAddress. + * + * @param buffer the buffer to write. + * @param groupOriginAddress the address of the group. + * @param newChildrenAddress the absolute address of the child. + * @param formatOptions file format options. + */ + public static void updateChildrenAddress(final FusionDictionaryBufferInterface buffer, + final int groupOriginAddress, final int newChildrenAddress, + final FormatOptions formatOptions) { + final int originalPosition = buffer.position(); + buffer.position(groupOriginAddress); + final int flags = buffer.readUnsignedByte(); + final int parentAddress = BinaryDictInputOutput.readParentAddress(buffer, formatOptions); + skipString(buffer, (flags & FormatSpec.FLAG_HAS_MULTIPLE_CHARS) != 0); + if ((FormatSpec.FLAG_IS_TERMINAL) != 0) buffer.readUnsignedByte(); + final int childrenOffset = newChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS + ? FormatSpec.NO_CHILDREN_ADDRESS : newChildrenAddress - buffer.position(); + putSInt24(buffer, childrenOffset); + buffer.position(originalPosition); + } } diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index b431a4da9..3e6965a17 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -124,8 +124,7 @@ public final class BinaryDictInputOutput { /** * A class grouping utility function for our specific character encoding. */ - private static final class CharEncoding { - + static final class CharEncoding { private static final int MINIMAL_ONE_BYTE_CHARACTER_VALUE = 0x20; private static final int MAXIMAL_ONE_BYTE_CHARACTER_VALUE = 0xFF; @@ -263,7 +262,7 @@ public final class BinaryDictInputOutput { * @param buffer the buffer, positioned over an encoded character. * @return the character code. */ - private static int readChar(final FusionDictionaryBufferInterface buffer) { + static int readChar(final FusionDictionaryBufferInterface buffer) { int character = buffer.readUnsignedByte(); if (!fitsOnOneByte(character)) { if (FormatSpec.GROUP_CHARACTERS_TERMINATOR == character) { @@ -1219,7 +1218,7 @@ public final class BinaryDictInputOutput { } } - private static int readParentAddress(final FusionDictionaryBufferInterface buffer, + static int readParentAddress(final FusionDictionaryBufferInterface buffer, final FormatOptions formatOptions) { if (supportsDynamicUpdate(formatOptions)) { final int parentAddress = buffer.readUnsignedInt24(); -- cgit v1.2.3-83-g751a From 58fe5a421f3334641209300c5bc60c0e6a842220 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 27 Sep 2012 19:01:17 +0900 Subject: Fix gesture detection algorithm This change also * Introduces adaptive gesture detecting threshold for time domain in addition to length domain. * Tunes the parameters for detecting gesture after fast typing. * Fixes a bug in dismissing gesture floating preview text. * Cleanup debug messages Bug: 7218902 Change-Id: Iafccd872c6efe0c3b5ae65fa40b04c80d9f139c7 --- .../inputmethod/keyboard/PointerTracker.java | 86 +++++------ .../keyboard/internal/GestureStroke.java | 166 +++++++++++++-------- .../internal/GestureStrokeWithPreviewPoints.java | 2 +- .../com/android/inputmethod/latin/LatinIME.java | 47 ++++-- 4 files changed, 172 insertions(+), 129 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 5248b8abb..100a9c618 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -168,8 +168,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element { private static long sLastLetterTypingUpTime; private static final InputPointers sAggregratedPointers = new InputPointers( GestureStroke.DEFAULT_CAPACITY); - private static int sLastRecognitionPointSize = 0; - private static long sLastRecognitionTime = 0; + private static int sLastRecognitionPointSize = 0; // synchronized using sAggregratedPointers + private static long sLastRecognitionTime = 0; // synchronized using sAggregratedPointers // The position and time at which first down event occurred. private long mDownTime; @@ -306,9 +306,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); if (DEBUG_LISTENER) { - Log.d(TAG, "onPress : " + KeyDetector.printableCode(key) - + " ignoreModifier=" + ignoreModifierKey - + " enabled=" + key.isEnabled()); + Log.d(TAG, String.format("[%d] onPress : %s%s%s", mPointerId, + KeyDetector.printableCode(key), + ignoreModifierKey ? " ignoreModifier" : "", + key.isEnabled() ? "" : " disabled")); } if (ignoreModifierKey) { return false; @@ -331,10 +332,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element { final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState(); final int code = altersCode ? key.getAltCode() : primaryCode; if (DEBUG_LISTENER) { - Log.d(TAG, "onCodeInput: " + Keyboard.printableCode(code) - + " text=" + key.getOutputText() + " x=" + x + " y=" + y - + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode - + " enabled=" + key.isEnabled()); + final String output = code == Keyboard.CODE_OUTPUT_TEXT + ? key.getOutputText() : Keyboard.printableCode(code); + Log.d(TAG, String.format("[%d] onCodeInput: %4d %4d %s%s%s", mPointerId, x, y, + output, ignoreModifierKey ? " ignoreModifier" : "", + altersCode ? " altersCode" : "", key.isEnabled() ? "" : " disabled")); } if (ProductionFlag.IS_EXPERIMENTAL) { ResearchLogger.pointerTracker_callListenerOnCodeInput(key, x, y, ignoreModifierKey, @@ -362,9 +364,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); if (DEBUG_LISTENER) { - Log.d(TAG, "onRelease : " + Keyboard.printableCode(primaryCode) - + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey - + " enabled="+ key.isEnabled()); + Log.d(TAG, String.format("[%d] onRelease : %s%s%s%s", mPointerId, + Keyboard.printableCode(primaryCode), + withSliding ? " sliding" : "", ignoreModifierKey ? " ignoreModifier" : "", + key.isEnabled() ? "": " disabled")); } if (ProductionFlag.IS_EXPERIMENTAL) { ResearchLogger.pointerTracker_callListenerOnRelease(key, primaryCode, withSliding, @@ -380,7 +383,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { private void callListenerOnCancelInput() { if (DEBUG_LISTENER) { - Log.d(TAG, "onCancelInput"); + Log.d(TAG, String.format("[%d] onCancelInput", mPointerId)); } if (ProductionFlag.IS_EXPERIMENTAL) { ResearchLogger.pointerTracker_callListenerOnCancelInput(); @@ -389,6 +392,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } private void setKeyDetectorInner(final KeyDetector keyDetector) { + final Keyboard keyboard = keyDetector.getKeyboard(); + if (keyDetector == mKeyDetector && keyboard == mKeyboard) { + return; + } mKeyDetector = keyDetector; mKeyboard = keyDetector.getKeyboard(); mGestureStrokeWithPreviewPoints.setKeyboardGeometry(mKeyboard.mMostCommonKeyWidth); @@ -551,10 +558,15 @@ public final class PointerTracker implements PointerTrackerQueue.Element { return; } if (DEBUG_LISTENER) { - Log.d(TAG, "onStartBatchInput"); + Log.d(TAG, String.format("[%d] onStartBatchInput", mPointerId)); } sInGesture = true; - mListener.onStartBatchInput(); + synchronized (sAggregratedPointers) { + sAggregratedPointers.reset(); + sLastRecognitionPointSize = 0; + sLastRecognitionTime = 0; + mListener.onStartBatchInput(); + } final boolean isOldestTracker = sPointerTrackerQueue.getOldestElement() == this; mDrawingProxy.showGesturePreviewTrail(this, isOldestTracker); } @@ -569,7 +581,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element { sLastRecognitionPointSize = size; sLastRecognitionTime = eventTime; if (DEBUG_LISTENER) { - Log.d(TAG, "onUpdateBatchInput: batchPoints=" + size); + Log.d(TAG, String.format("[%d] onUpdateBatchInput: batchPoints=%d", + mPointerId, size)); } mListener.onUpdateBatchInput(sAggregratedPointers); } @@ -582,36 +595,19 @@ public final class PointerTracker implements PointerTrackerQueue.Element { private void mayEndBatchInput() { synchronized (sAggregratedPointers) { mGestureStrokeWithPreviewPoints.appendAllBatchPoints(sAggregratedPointers); - mGestureStrokeWithPreviewPoints.reset(); if (getActivePointerTrackerCount() == 1) { if (DEBUG_LISTENER) { - Log.d(TAG, "onEndBatchInput: batchPoints=" - + sAggregratedPointers.getPointerSize()); + Log.d(TAG, String.format("[%d] onEndBatchInput : batchPoints=%d", + mPointerId, sAggregratedPointers.getPointerSize())); } sInGesture = false; mListener.onEndBatchInput(sAggregratedPointers); - clearBatchInputPointsOfAllPointerTrackers(); } } final boolean isOldestTracker = sPointerTrackerQueue.getOldestElement() == this; mDrawingProxy.showGesturePreviewTrail(this, isOldestTracker); } - private static void abortBatchInput() { - clearBatchInputPointsOfAllPointerTrackers(); - } - - private static void clearBatchInputPointsOfAllPointerTrackers() { - final int trackersSize = sTrackers.size(); - for (int i = 0; i < trackersSize; ++i) { - final PointerTracker tracker = sTrackers.get(i); - tracker.mGestureStrokeWithPreviewPoints.reset(); - } - sAggregratedPointers.reset(); - sLastRecognitionPointSize = 0; - sLastRecognitionTime = 0; - } - public void processMotionEvent(final int action, final int x, final int y, final long eventTime, final KeyEventHandler handler) { switch (action) { @@ -681,18 +677,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (getActivePointerTrackerCount() == 1) { sGestureFirstDownTime = eventTime; } - onGestureDownEvent(x, y, eventTime); + mGestureStrokeWithPreviewPoints.onDownEvent(x, y, eventTime, sGestureFirstDownTime, + sLastLetterTypingUpTime); } } - private void onGestureDownEvent(final int x, final int y, final long eventTime) { - mIsDetectingGesture = true; - mGestureStrokeWithPreviewPoints.setLastLetterTypingTime(eventTime, sLastLetterTypingUpTime); - final int elapsedTimeFromFirstDown = (int)(eventTime - sGestureFirstDownTime); - mGestureStrokeWithPreviewPoints.addPoint(x, y, elapsedTimeFromFirstDown, - true /* isMajorEvent */); - } - private void onDownEventInternal(final int x, final int y, final long eventTime) { Key key = onDownKey(x, y, eventTime); // Sliding key is allowed when 1) enabled by configuration, 2) this pointer starts sliding @@ -925,9 +914,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { mayEndBatchInput(); return; } - // This event will be recognized as a regular code input. Clear unused possible batch points - // so they are not mistakenly displayed as preview. - clearBatchInputPointsOfAllPointerTrackers(); + if (mKeyAlreadyProcessed) { return; } @@ -941,7 +928,6 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } public void onShowMoreKeysPanel(final int x, final int y, final KeyEventHandler handler) { - abortBatchInput(); onLongPressed(); mIsShowingMoreKeysPanel = true; onDownEvent(x, y, SystemClock.uptimeMillis(), handler); @@ -1029,7 +1015,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { final long eventTime) { final Key key = mKeyDetector.detectHitKey(x, y); final String code = KeyDetector.printableCode(key); - Log.d(TAG, String.format("%s%s[%d] %4d %4d %5d %s", title, - (mKeyAlreadyProcessed ? "-" : " "), mPointerId, x, y, eventTime, code)); + Log.d(TAG, String.format("[%d]%s%s %4d %4d %5d %s", mPointerId, + (mKeyAlreadyProcessed ? "-" : " "), title, x, y, eventTime, code)); } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java index 9fe6fa3f8..c0e92df32 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java +++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java @@ -22,6 +22,7 @@ import com.android.inputmethod.latin.ResizableIntArray; public class GestureStroke { private static final String TAG = GestureStroke.class.getSimpleName(); private static final boolean DEBUG = false; + private static final boolean DEBUG_SPEED = false; public static final int DEFAULT_CAPACITY = 128; @@ -29,42 +30,52 @@ public class GestureStroke { private final ResizableIntArray mEventTimes = new ResizableIntArray(DEFAULT_CAPACITY); private final ResizableIntArray mXCoordinates = new ResizableIntArray(DEFAULT_CAPACITY); private final ResizableIntArray mYCoordinates = new ResizableIntArray(DEFAULT_CAPACITY); - private int mIncrementalRecognitionSize; - private int mLastIncrementalBatchSize; - private long mLastMajorEventTime; - private int mLastMajorEventX; - private int mLastMajorEventY; - private boolean mAfterFastTyping; - private int mKeyWidth; - private int mStartGestureLengthThresholdAfterFastTyping; // pixel - private int mStartGestureLengthThreshold; // pixel - private int mMinGestureSamplingLength; // pixel - private int mGestureRecognitionSpeedThreshold; // pixel / sec + private int mKeyWidth; // pixel + // Static threshold for starting gesture detection private int mDetectFastMoveSpeedThreshold; // pixel /sec private int mDetectFastMoveTime; private int mDetectFastMoveX; private int mDetectFastMoveY; + // Dynamic threshold for gesture after fast typing + private boolean mAfterFastTyping; + private int mGestureDynamicDistanceThresholdFrom; // pixel + private int mGestureDynamicDistanceThresholdTo; // pixel + // Variables for gesture sampling + private int mGestureSamplingMinimumDistance; // pixel + private long mLastMajorEventTime; + private int mLastMajorEventX; + private int mLastMajorEventY; + // Variables for gesture recognition + private int mGestureRecognitionSpeedThreshold; // pixel / sec + private int mIncrementalRecognitionSize; + private int mLastIncrementalBatchSize; // TODO: Move some of these to resource. - private static final int GESTURE_AFTER_FAST_TYPING_DURATION_THRESHOLD = 350; // msec - private static final float START_GESTURE_LENGTH_THRESHOLD_AFTER_FAST_TYPING_RATIO_TO_KEY_WIDTH = - 8.0f; - private static final int START_GESTURE_LENGTH_THRESHOLD_DECAY_DURATION = 400; // msec - private static final float START_GESTURE_LENGTH_THRESHOLD_RATIO_TO_KEY_WIDTH = 0.6f; - private static final int START_GESTURE_DURATION_THRESHOLD = 70; // msec - private static final int MIN_GESTURE_RECOGNITION_TIME = 100; // msec - private static final float MIN_GESTURE_SAMPLING_RATIO_TO_KEY_WIDTH = 1.0f / 6.0f; - private static final float GESTURE_RECOGNITION_SPEED_THRESHOLD_RATIO_TO_KEY_WIDTH = - 5.5f; // keyWidth / sec - private static final float DETECT_FAST_MOVE_SPEED_THRESHOLD_RATIO_TO_KEY_WIDTH = - 5.0f; // keyWidth / sec - private static final int MSEC_PER_SEC = 1000; - public static final boolean hasRecognitionTimePast( - final long currentTime, final long lastRecognitionTime) { - return currentTime > lastRecognitionTime + MIN_GESTURE_RECOGNITION_TIME; - } + // Static threshold for gesture after fast typing + public static final int GESTURE_STATIC_TIME_THRESHOLD_AFTER_FAST_TYPING = 350; // msec + + // Static threshold for starting gesture detection + private static final float DETECT_FAST_MOVE_SPEED_THRESHOLD = 1.5f; // keyWidth / sec + + // Dynamic threshold for gesture after fast typing + private static final int GESTURE_DYNAMIC_THRESHOLD_DECAY_DURATION = 450; // msec + // Time based threshold values + private static final int GESTURE_DYNAMIC_TIME_THRESHOLD_FROM = 300; // msec + private static final int GESTURE_DYNAMIC_TIME_THRESHOLD_TO = 20; // msec + // Distance based threshold values + private static final float GESTURE_DYNAMIC_DISTANCE_THRESHOLD_FROM = 6.0f; // keyWidth + private static final float GESTURE_DYNAMIC_DISTANCE_THRESHOLD_TO = 0.35f; // keyWidth + + // Parameters for gesture sampling + private static final float GESTURE_SAMPLING_MINIMUM_DISTANCE = 1.0f / 6.0f; // keyWidth + + // Parameters for gesture recognition + private static final int GESTURE_RECOGNITION_MINIMUM_TIME = 100; // msec + private static final float GESTURE_RECOGNITION_SPEED_THRESHOLD = 5.5f; // keyWidth / sec + + private static final int MSEC_PER_SEC = 1000; public GestureStroke(final int pointerId) { mPointerId = pointerId; @@ -73,41 +84,58 @@ public class GestureStroke { public void setKeyboardGeometry(final int keyWidth) { mKeyWidth = keyWidth; // TODO: Find an appropriate base metric for these length. Maybe diagonal length of the key? - mStartGestureLengthThresholdAfterFastTyping = (int)(keyWidth - * START_GESTURE_LENGTH_THRESHOLD_AFTER_FAST_TYPING_RATIO_TO_KEY_WIDTH); - mStartGestureLengthThreshold = - (int)(keyWidth * START_GESTURE_LENGTH_THRESHOLD_RATIO_TO_KEY_WIDTH); - mMinGestureSamplingLength = (int)(keyWidth * MIN_GESTURE_SAMPLING_RATIO_TO_KEY_WIDTH); + mDetectFastMoveSpeedThreshold = (int)(keyWidth * DETECT_FAST_MOVE_SPEED_THRESHOLD); + mGestureDynamicDistanceThresholdFrom = + (int)(keyWidth * GESTURE_DYNAMIC_DISTANCE_THRESHOLD_FROM); + mGestureDynamicDistanceThresholdTo = + (int)(keyWidth * GESTURE_DYNAMIC_DISTANCE_THRESHOLD_TO); + mGestureSamplingMinimumDistance = (int)(keyWidth * GESTURE_SAMPLING_MINIMUM_DISTANCE); mGestureRecognitionSpeedThreshold = - (int)(keyWidth * GESTURE_RECOGNITION_SPEED_THRESHOLD_RATIO_TO_KEY_WIDTH); - mDetectFastMoveSpeedThreshold = - (int)(keyWidth * DETECT_FAST_MOVE_SPEED_THRESHOLD_RATIO_TO_KEY_WIDTH); + (int)(keyWidth * GESTURE_RECOGNITION_SPEED_THRESHOLD); if (DEBUG) { - Log.d(TAG, "[" + mPointerId + "] setKeyboardGeometry: keyWidth=" + keyWidth - + " tL0=" + mStartGestureLengthThresholdAfterFastTyping - + " tL=" + mStartGestureLengthThreshold); + Log.d(TAG, String.format( + "[%d] setKeyboardGeometry: keyWidth=%3d tT=%3d >> %3d tD=%3d >> %3d", + mPointerId, keyWidth, + GESTURE_DYNAMIC_TIME_THRESHOLD_FROM, + GESTURE_DYNAMIC_TIME_THRESHOLD_TO, + mGestureDynamicDistanceThresholdFrom, + mGestureDynamicDistanceThresholdTo)); } } - public void setLastLetterTypingTime(final long downTime, final long lastTypingTime) { - final long elpasedTimeAfterTyping = downTime - lastTypingTime; - if (elpasedTimeAfterTyping < GESTURE_AFTER_FAST_TYPING_DURATION_THRESHOLD) { + public void onDownEvent(final int x, final int y, final long downTime, + final long gestureFirstDownTime, final long lastTypingTime) { + reset(); + final long elapsedTimeAfterTyping = downTime - lastTypingTime; + if (elapsedTimeAfterTyping < GESTURE_STATIC_TIME_THRESHOLD_AFTER_FAST_TYPING) { mAfterFastTyping = true; } if (DEBUG) { - Log.d(TAG, "[" + mPointerId + "] setLastTypingTime: dT=" + elpasedTimeAfterTyping - + " afterFastTyping=" + mAfterFastTyping); + Log.d(TAG, String.format("[%d] onDownEvent: dT=%3d%s", mPointerId, + elapsedTimeAfterTyping, mAfterFastTyping ? " afterFastTyping" : "")); } + final int elapsedTimeFromFirstDown = (int)(downTime - gestureFirstDownTime); + addPoint(x, y, elapsedTimeFromFirstDown, true /* isMajorEvent */); } - private int getStartGestureLengthThreshold(final int deltaTime) { - if (!mAfterFastTyping || deltaTime >= START_GESTURE_LENGTH_THRESHOLD_DECAY_DURATION) { - return mStartGestureLengthThreshold; + private int getGestureDynamicDistanceThreshold(final int deltaTime) { + if (!mAfterFastTyping || deltaTime >= GESTURE_DYNAMIC_THRESHOLD_DECAY_DURATION) { + return mGestureDynamicDistanceThresholdTo; } final int decayedThreshold = - (mStartGestureLengthThresholdAfterFastTyping - mStartGestureLengthThreshold) - * deltaTime / START_GESTURE_LENGTH_THRESHOLD_DECAY_DURATION; - return mStartGestureLengthThresholdAfterFastTyping - decayedThreshold; + (mGestureDynamicDistanceThresholdFrom - mGestureDynamicDistanceThresholdTo) + * deltaTime / GESTURE_DYNAMIC_THRESHOLD_DECAY_DURATION; + return mGestureDynamicDistanceThresholdFrom - decayedThreshold; + } + + private int getGestureDynamicTimeThreshold(final int deltaTime) { + if (!mAfterFastTyping || deltaTime >= GESTURE_DYNAMIC_THRESHOLD_DECAY_DURATION) { + return GESTURE_DYNAMIC_TIME_THRESHOLD_TO; + } + final int decayedThreshold = + (GESTURE_DYNAMIC_TIME_THRESHOLD_FROM - GESTURE_DYNAMIC_TIME_THRESHOLD_TO) + * deltaTime / GESTURE_DYNAMIC_THRESHOLD_DECAY_DURATION; + return GESTURE_DYNAMIC_TIME_THRESHOLD_FROM - decayedThreshold; } public boolean isStartOfAGesture() { @@ -120,21 +148,24 @@ public class GestureStroke { } final int lastIndex = size - 1; final int deltaTime = mEventTimes.get(lastIndex) - mDetectFastMoveTime; - final int deltaLength = getDistance( + final int deltaDistance = getDistance( mXCoordinates.get(lastIndex), mYCoordinates.get(lastIndex), mDetectFastMoveX, mDetectFastMoveY); - final int startGestureLengthThreshold = getStartGestureLengthThreshold(deltaTime); - final boolean isStartOfAGesture = deltaTime > START_GESTURE_DURATION_THRESHOLD - && deltaLength > startGestureLengthThreshold; + final int distanceThreshold = getGestureDynamicDistanceThreshold(deltaTime); + final int timeThreshold = getGestureDynamicTimeThreshold(deltaTime); + final boolean isStartOfAGesture = deltaTime >= timeThreshold + && deltaDistance >= distanceThreshold; if (DEBUG) { - Log.d(TAG, "[" + mPointerId + "] isStartOfAGesture: dT=" + deltaTime - + " dL=" + deltaLength + " tL=" + startGestureLengthThreshold - + " points=" + size + (isStartOfAGesture ? " Detect start of a gesture" : "")); + Log.d(TAG, String.format("[%d] isStartOfAGesture: dT=%3d tT=%3d dD=%3d tD=%3d%s%s", + mPointerId, deltaTime, timeThreshold, + deltaDistance, distanceThreshold, + mAfterFastTyping ? " afterFastTyping" : "", + isStartOfAGesture ? " startOfAGesture" : "")); } return isStartOfAGesture; } - public void reset() { + protected void reset() { mIncrementalRecognitionSize = 0; mLastIncrementalBatchSize = 0; mEventTimes.setLength(0); @@ -167,15 +198,17 @@ public class GestureStroke { if (msecs > 0) { final int pixels = getDistance(lastX, lastY, x, y); final int pixelsPerSec = pixels * MSEC_PER_SEC; - if (DEBUG) { + if (DEBUG_SPEED) { final float speed = (float)pixelsPerSec / msecs / mKeyWidth; - Log.d(TAG, String.format("[" + mPointerId + "] speed=%.3f", speed)); + Log.d(TAG, String.format("[%d] detectFastMove: speed=%5.2f", mPointerId, speed)); } // Equivalent to (pixels / msecs < mStartSpeedThreshold / MSEC_PER_SEC) if (mDetectFastMoveTime == 0 && pixelsPerSec > mDetectFastMoveSpeedThreshold * msecs) { if (DEBUG) { - Log.d(TAG, "[" + mPointerId + "] detect fast move: T=" - + time + " points = " + size); + final float speed = (float)pixelsPerSec / msecs / mKeyWidth; + Log.d(TAG, String.format( + "[%d] detectFastMove: speed=%5.2f T=%3d points=%3d fastMove", + mPointerId, speed, time, size)); } mDetectFastMoveTime = time; mDetectFastMoveX = x; @@ -192,8 +225,8 @@ public class GestureStroke { appendPoint(x, y, time); updateMajorEvent(x, y, time); } else { - final int dist = detectFastMove(x, y, time); - if (dist > mMinGestureSamplingLength) { + final int distance = detectFastMove(x, y, time); + if (distance > mGestureSamplingMinimumDistance) { appendPoint(x, y, time); } } @@ -216,6 +249,11 @@ public class GestureStroke { } } + public static final boolean hasRecognitionTimePast( + final long currentTime, final long lastRecognitionTime) { + return currentTime > lastRecognitionTime + GESTURE_RECOGNITION_MINIMUM_TIME; + } + public void appendAllBatchPoints(final InputPointers out) { appendBatchPoints(out, mEventTimes.getLength()); } diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java index 5b3f31805..05e0a2ec3 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java +++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java @@ -38,7 +38,7 @@ public final class GestureStrokeWithPreviewPoints extends GestureStroke { } @Override - public void reset() { + protected void reset() { super.reset(); mStrokeId++; mLastPreviewSize = 0; diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 3e893303f..268d36ad2 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1402,6 +1402,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction @Override public void onStartBatchInput() { + BatchInputUpdater.getInstance().onStartBatchInput(); mConnection.beginBatchEdit(); if (mWordComposer.isComposingWord()) { if (ProductionFlag.IS_INTERNAL) { @@ -1433,6 +1434,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction private static final class BatchInputUpdater implements Handler.Callback { private final Handler mHandler; private LatinIME mLatinIme; + private boolean mInBatchInput; // synchornized using "this". private BatchInputUpdater() { final HandlerThread handlerThread = new HandlerThread( @@ -1456,17 +1458,32 @@ public final class LatinIME extends InputMethodService implements KeyboardAction public boolean handleMessage(final Message msg) { switch (msg.what) { case MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP: - final SuggestedWords suggestedWords = getSuggestedWordsGesture( - (InputPointers)msg.obj, mLatinIme); - showGesturePreviewAndSuggestionStrip( - suggestedWords, false /* dismissGestureFloatingPreviewText */, mLatinIme); + updateBatchInput((InputPointers)msg.obj, mLatinIme); break; } return true; } - public void updateGesturePreviewAndSuggestionStrip(final InputPointers batchPointers, + // Run in the UI thread. + public synchronized void onStartBatchInput() { + mInBatchInput = true; + } + + // Run in the Handler thread. + private synchronized void updateBatchInput(final InputPointers batchPointers, final LatinIME latinIme) { + if (!mInBatchInput) { + // Batch input has ended while the message was being delivered. + return; + } + final SuggestedWords suggestedWords = getSuggestedWordsGestureLocked( + batchPointers, latinIme); + latinIme.mHandler.showGesturePreviewAndSuggestionStrip( + suggestedWords, false /* dismissGestureFloatingPreviewText */); + } + + // Run in the UI thread. + public void onUpdateBatchInput(final InputPointers batchPointers, final LatinIME latinIme) { mLatinIme = latinIme; if (mHandler.hasMessages(MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP)) { return; @@ -1476,15 +1493,20 @@ public final class LatinIME extends InputMethodService implements KeyboardAction .sendToTarget(); } - public void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords, - final boolean dismissGestureFloatingPreviewText, final LatinIME latinIme) { + // Run in the UI thread. + public synchronized SuggestedWords onEndBatchInput(final InputPointers batchPointers, + final LatinIME latinIme) { + mInBatchInput = false; + final SuggestedWords suggestedWords = getSuggestedWordsGestureLocked( + batchPointers, latinIme); latinIme.mHandler.showGesturePreviewAndSuggestionStrip( - suggestedWords, dismissGestureFloatingPreviewText); + suggestedWords, true /* dismissGestureFloatingPreviewText */); + return suggestedWords; } // {@link LatinIME#getSuggestedWords(int)} method calls with same session id have to // be synchronized. - public synchronized SuggestedWords getSuggestedWordsGesture( + private static SuggestedWords getSuggestedWordsGestureLocked( final InputPointers batchPointers, final LatinIME latinIme) { latinIme.mWordComposer.setBatchInputPointers(batchPointers); return latinIme.getSuggestedWords(Suggest.SESSION_GESTURE); @@ -1505,16 +1527,13 @@ public final class LatinIME extends InputMethodService implements KeyboardAction @Override public void onUpdateBatchInput(final InputPointers batchPointers) { - BatchInputUpdater.getInstance().updateGesturePreviewAndSuggestionStrip(batchPointers, this); + BatchInputUpdater.getInstance().onUpdateBatchInput(batchPointers, this); } @Override public void onEndBatchInput(final InputPointers batchPointers) { - final BatchInputUpdater batchInputUpdater = BatchInputUpdater.getInstance(); - final SuggestedWords suggestedWords = batchInputUpdater.getSuggestedWordsGesture( + final SuggestedWords suggestedWords = BatchInputUpdater.getInstance().onEndBatchInput( batchPointers, this); - batchInputUpdater.showGesturePreviewAndSuggestionStrip( - suggestedWords, true /* dismissGestureFloatingPreviewText */, this); final String batchInputText = (suggestedWords.size() > 0) ? suggestedWords.getWord(0) : null; if (TextUtils.isEmpty(batchInputText)) { -- cgit v1.2.3-83-g751a From 7339a62a1368b632c0cedaf1d876a0e8590a47ed Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Mon, 1 Oct 2012 14:26:38 +0900 Subject: Fix NPE observed only by monkey test Bug: 7258660 Change-Id: I286c704b32efeada8505d953438f2595166f7e8f --- .../latin/suggestions/MoreSuggestions.java | 9 ++-- .../latin/suggestions/SuggestionStripView.java | 59 ++++++++++++---------- 2 files changed, 35 insertions(+), 33 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java index e9bf0fac4..4ad82abdd 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java @@ -22,7 +22,6 @@ import android.graphics.drawable.Drawable; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.internal.KeyboardBuilder; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.internal.KeyboardParams; @@ -175,11 +174,11 @@ public final class MoreSuggestions extends Keyboard { } public Builder layout(final SuggestedWords suggestions, final int fromPos, - final int maxWidth, final int minWidth, final int maxRow) { - final Keyboard keyboard = KeyboardSwitcher.getInstance().getKeyboard(); + final int maxWidth, final int minWidth, final int maxRow, + final Keyboard parentKeyboard) { final int xmlId = R.xml.kbd_suggestions_pane_template; - load(xmlId, keyboard.mId); - mParams.mVerticalGap = mParams.mTopPadding = keyboard.mVerticalGap / 2; + load(xmlId, parentKeyboard.mId); + mParams.mVerticalGap = mParams.mTopPadding = parentKeyboard.mVerticalGap / 2; final int count = mParams.layout(suggestions, fromPos, maxWidth, minWidth, maxRow, mPaneView); diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index e926fa209..94283f242 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -52,7 +52,9 @@ import android.widget.PopupWindow; import android.widget.RelativeLayout; import android.widget.TextView; +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardActionListener; +import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardView; import com.android.inputmethod.keyboard.MoreKeysPanel; import com.android.inputmethod.keyboard.PointerTracker; @@ -751,36 +753,37 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick } private boolean showMoreSuggestions() { + final Keyboard parentKeyboard = KeyboardSwitcher.getInstance().getKeyboard(); + if (parentKeyboard == null) { + return false; + } final SuggestionStripViewParams params = mParams; - if (params.mMoreSuggestionsAvailable) { - final int stripWidth = getWidth(); - final View container = mMoreSuggestionsContainer; - final int maxWidth = stripWidth - container.getPaddingLeft() - - container.getPaddingRight(); - final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder; - builder.layout(mSuggestedWords, params.mSuggestionsCountInStrip, maxWidth, - (int)(maxWidth * params.mMinMoreSuggestionsWidth), - params.getMaxMoreSuggestionsRow()); - mMoreSuggestionsView.setKeyboard(builder.build()); - container.measure( - ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - - final MoreKeysPanel moreKeysPanel = mMoreSuggestionsView; - final int pointX = stripWidth / 2; - final int pointY = -params.mMoreSuggestionsBottomGap; - moreKeysPanel.showMoreKeysPanel( - this, mMoreSuggestionsController, pointX, pointY, - mMoreSuggestionsWindow, mMoreSuggestionsListener); - mMoreSuggestionsMode = MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING; - mOriginX = mLastX; - mOriginY = mLastY; - mKeyboardView.dimEntireKeyboard(true); - for (int i = 0; i < params.mSuggestionsCountInStrip; i++) { - mWords.get(i).setPressed(false); - } - return true; + if (!params.mMoreSuggestionsAvailable) { + return false; } - return false; + final int stripWidth = getWidth(); + final View container = mMoreSuggestionsContainer; + final int maxWidth = stripWidth - container.getPaddingLeft() - container.getPaddingRight(); + final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder; + builder.layout(mSuggestedWords, params.mSuggestionsCountInStrip, maxWidth, + (int)(maxWidth * params.mMinMoreSuggestionsWidth), + params.getMaxMoreSuggestionsRow(), parentKeyboard); + mMoreSuggestionsView.setKeyboard(builder.build()); + container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + + final MoreKeysPanel moreKeysPanel = mMoreSuggestionsView; + final int pointX = stripWidth / 2; + final int pointY = -params.mMoreSuggestionsBottomGap; + moreKeysPanel.showMoreKeysPanel(this, mMoreSuggestionsController, pointX, pointY, + mMoreSuggestionsWindow, mMoreSuggestionsListener); + mMoreSuggestionsMode = MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING; + mOriginX = mLastX; + mOriginY = mLastY; + mKeyboardView.dimEntireKeyboard(true); + for (int i = 0; i < params.mSuggestionsCountInStrip; i++) { + mWords.get(i).setPressed(false); + } + return true; } // Working variables for onLongClick and dispatchTouchEvent. -- cgit v1.2.3-83-g751a From 574b80aacee95df26e85e6b78876a73d7076a672 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Mon, 1 Oct 2012 16:03:21 +0900 Subject: Remove debug prints. Bug: 7226098 Change-Id: Ibacb740022a6af56c9d555d6797dd402a89f6ca4 --- .../com/android/inputmethod/latin/LatinIME.java | 4 ++++ .../inputmethod/latin/RichInputConnection.java | 25 +++++++++++----------- 2 files changed, 17 insertions(+), 12 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 268d36ad2..311355374 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1878,6 +1878,10 @@ public final class LatinIME extends InputMethodService implements KeyboardAction mIsAutoCorrectionIndicatorOn = newAutoCorrectionIndicator; final CharSequence textWithUnderline = getTextWithUnderline(mWordComposer.getTypedWord()); + // TODO: when called from an updateSuggestionStrip() call that results from a posted + // message, this is called outside any batch edit. Potentially, this may result in some + // janky flickering of the screen, although the display speed makes it unlikely in + // the practice. mConnection.setComposingText(textWithUnderline, 1); } } diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index 1acca5860..b27db579f 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -45,6 +45,7 @@ public final class RichInputConnection { private static final String TAG = RichInputConnection.class.getSimpleName(); private static final boolean DBG = false; private static final boolean DEBUG_PREVIOUS_TEXT = false; + private static final boolean DEBUG_BATCH_NESTING = false; // Provision for a long word pair and a separator private static final int LOOKBACK_CHARACTER_NUM = BinaryDictionary.MAX_WORD_LENGTH * 2 + 1; private static final Pattern spaceRegex = Pattern.compile("\\s+"); @@ -128,7 +129,7 @@ public final class RichInputConnection { Log.e(TAG, "Nest level too deep : " + mNestLevel); } } - checkBatchEdit(); + if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); } @@ -163,7 +164,7 @@ public final class RichInputConnection { } public void finishComposingText() { - checkBatchEdit(); + if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); mCommittedTextBeforeComposingText.append(mComposingText); mCurrentCursorPosition += mComposingText.length(); @@ -177,7 +178,7 @@ public final class RichInputConnection { } public void commitText(final CharSequence text, final int i) { - checkBatchEdit(); + if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); mCommittedTextBeforeComposingText.append(text); mCurrentCursorPosition += text.length() - mComposingText.length(); @@ -247,7 +248,7 @@ public final class RichInputConnection { } public void deleteSurroundingText(final int i, final int j) { - checkBatchEdit(); + if (DEBUG_BATCH_NESTING) checkBatchEdit(); final int remainingChars = mComposingText.length() - i; if (remainingChars >= 0) { mComposingText.setLength(remainingChars); @@ -283,7 +284,7 @@ public final class RichInputConnection { } public void sendKeyEvent(final KeyEvent keyEvent) { - checkBatchEdit(); + if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) { if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); // This method is only called for enter or backspace when speaking to old @@ -331,7 +332,7 @@ public final class RichInputConnection { } public void setComposingText(final CharSequence text, final int i) { - checkBatchEdit(); + if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); mCurrentCursorPosition += text.length() - mComposingText.length(); mComposingText.setLength(0); @@ -347,7 +348,7 @@ public final class RichInputConnection { } public void setSelection(final int from, final int to) { - checkBatchEdit(); + if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); if (null != mIC) { mIC.setSelection(from, to); @@ -361,7 +362,7 @@ public final class RichInputConnection { } public void commitCorrection(final CorrectionInfo correctionInfo) { - checkBatchEdit(); + if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); // This has no effect on the text field and does not change its content. It only makes // TextView flash the text for a second based on indices contained in the argument. @@ -375,7 +376,7 @@ public final class RichInputConnection { } public void commitCompletion(final CompletionInfo completionInfo) { - checkBatchEdit(); + if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); final CharSequence text = completionInfo.getText(); mCommittedTextBeforeComposingText.append(text); @@ -575,7 +576,7 @@ public final class RichInputConnection { } public void removeTrailingSpace() { - checkBatchEdit(); + if (DEBUG_BATCH_NESTING) checkBatchEdit(); final CharSequence lastOne = getTextBeforeCursor(1, 0); if (lastOne != null && lastOne.length() == 1 && lastOne.charAt(0) == Keyboard.CODE_SPACE) { @@ -631,7 +632,7 @@ public final class RichInputConnection { } public boolean revertDoubleSpace() { - checkBatchEdit(); + if (DEBUG_BATCH_NESTING) checkBatchEdit(); // Here we test whether we indeed have a period and a space before us. This should not // be needed, but it's there just in case something went wrong. final CharSequence textBeforeCursor = getTextBeforeCursor(2, 0); @@ -649,7 +650,7 @@ public final class RichInputConnection { } public boolean revertSwapPunctuation() { - checkBatchEdit(); + if (DEBUG_BATCH_NESTING) checkBatchEdit(); // Here we test whether we indeed have a space and something else before us. This should not // be needed, but it's there just in case something went wrong. final CharSequence textBeforeCursor = getTextBeforeCursor(2, 0); -- cgit v1.2.3-83-g751a From fb7e08ea8f40ebb4ac57e443f837043e7b57fd87 Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Fri, 28 Sep 2012 17:03:23 +0900 Subject: Add writeCharGroup. bug: 6669677 Change-Id: I36792ba9c511a5148c963096cc93ca8c2e0ee04e --- .../latin/makedict/BinaryDictIOUtils.java | 127 ++++++++++++++++++++- .../latin/makedict/BinaryDictInputOutput.java | 9 +- 2 files changed, 129 insertions(+), 7 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index c34d19d22..5c6417b04 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -22,9 +22,13 @@ import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.FusionDictio import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader; import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions; import com.android.inputmethod.latin.makedict.FusionDictionary.CharGroup; +import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; import java.io.IOException; +import java.io.OutputStream; import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Stack; @@ -251,7 +255,7 @@ public final class BinaryDictIOUtils { buffer.put((byte)newFlags); } - private static void putSInt24(final FusionDictionaryBufferInterface buffer, + private static void writeSInt24ToBuffer(final FusionDictionaryBufferInterface buffer, final int value) { final int absValue = Math.abs(value); buffer.put((byte)(((value < 0 ? 0x80 : 0) | (absValue >> 16)) & 0xFF)); @@ -259,6 +263,32 @@ public final class BinaryDictIOUtils { buffer.put((byte)(absValue & 0xFF)); } + private static void writeSInt24ToStream(final OutputStream destination, final int value) + throws IOException { + final int absValue = Math.abs(value); + destination.write((byte)(((value < 0 ? 0x80 : 0) | (absValue >> 16)) & 0xFF)); + destination.write((byte)((absValue >> 8) & 0xFF)); + destination.write((byte)(absValue & 0xFF)); + } + + private static void writeVariableAddress(final OutputStream destination, final int value) + throws IOException { + switch (BinaryDictInputOutput.getByteSize(value)) { + case 1: + destination.write((byte)value); + break; + case 2: + destination.write((byte)(0xFF & (value >> 8))); + destination.write((byte)(0xFF & value)); + break; + case 3: + destination.write((byte)(0xFF & (value >> 16))); + destination.write((byte)(0xFF & (value >> 8))); + destination.write((byte)(0xFF & value)); + break; + } + } + /** * Update a parent address in a CharGroup that is addressed by groupOriginAddress. * @@ -277,7 +307,7 @@ public final class BinaryDictIOUtils { } final int flags = buffer.readUnsignedByte(); final int parentOffset = newParentAddress - groupOriginAddress; - putSInt24(buffer, parentOffset); + writeSInt24ToBuffer(buffer, parentOffset); buffer.position(originalPosition); } @@ -293,6 +323,22 @@ public final class BinaryDictIOUtils { } } + private static void writeString(final OutputStream destination, final String word) + throws IOException { + final int length = word.length(); + for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) { + final int codePoint = word.codePointAt(i); + if (CharEncoding.getCharSize(codePoint) == 1) { + destination.write((byte)codePoint); + } else { + destination.write((byte)(0xFF & (codePoint >> 16))); + destination.write((byte)(0xFF & (codePoint >> 8))); + destination.write((byte)(0xFF & codePoint)); + } + } + destination.write((byte)FormatSpec.GROUP_CHARACTERS_TERMINATOR); + } + /** * Update a children address in a CharGroup that is addressed by groupOriginAddress. * @@ -312,7 +358,82 @@ public final class BinaryDictIOUtils { if ((FormatSpec.FLAG_IS_TERMINAL) != 0) buffer.readUnsignedByte(); final int childrenOffset = newChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS ? FormatSpec.NO_CHILDREN_ADDRESS : newChildrenAddress - buffer.position(); - putSInt24(buffer, childrenOffset); + writeSInt24ToBuffer(buffer, childrenOffset); buffer.position(originalPosition); } + + /** + * Write a char group to an output stream. + * A char group is an in-memory representation of a node in trie. + * A char group info is an on-disk representation of a node. + * + * @param destination the stream to write. + * @param info the char group info to be written. + */ + public static void writeCharGroup(final OutputStream destination, final CharGroupInfo info) + throws IOException { + destination.write((byte)info.mFlags); + final int parentOffset = info.mParentAddress == FormatSpec.NO_PARENT_ADDRESS ? + FormatSpec.NO_PARENT_ADDRESS : info.mParentAddress - info.mOriginalAddress; + writeSInt24ToStream(destination, parentOffset); + + for (int i = 0; i < info.mCharacters.length; ++i) { + if (CharEncoding.getCharSize(info.mCharacters[i]) == 1) { + destination.write((byte)info.mCharacters[i]); + } else { + writeSInt24ToStream(destination, info.mCharacters[i]); + } + } + if (info.mCharacters.length > 1) { + destination.write((byte)FormatSpec.GROUP_CHARACTERS_TERMINATOR); + } + + if ((info.mFlags & FormatSpec.FLAG_IS_TERMINAL) != 0) { + destination.write((byte)info.mFrequency); + } + + final int childrenOffset = info.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS ? + 0 : info.mChildrenAddress - info.mOriginalAddress; + writeSInt24ToStream(destination, childrenOffset); + + if (info.mShortcutTargets != null && info.mShortcutTargets.size() > 0) { + final int shortcutListSize = + BinaryDictInputOutput.getShortcutListSize(info.mShortcutTargets); + destination.write((byte)(shortcutListSize >> 8)); + destination.write((byte)(shortcutListSize & 0xFF)); + final Iterator shortcutIterator = info.mShortcutTargets.iterator(); + while (shortcutIterator.hasNext()) { + final WeightedString target = shortcutIterator.next(); + destination.write((byte)BinaryDictInputOutput.makeShortcutFlags( + shortcutIterator.hasNext(), target.mFrequency)); + writeString(destination, target.mWord); + } + } + + if (info.mBigrams != null) { + // TODO: Consolidate this code with the code that computes the size of the bigram list + // in BinaryDictionaryInputOutput#computeActualNodeSize + for (int i = 0; i < info.mBigrams.size(); ++i) { + final int bigramOffset = info.mBigrams.get(i).mAddress - info.mOriginalAddress; + final int bigramFrequency = info.mBigrams.get(i).mFrequency; + int bigramFlags = (i < info.mBigrams.size() - 1) + ? FormatSpec.FLAG_ATTRIBUTE_HAS_NEXT : 0; + bigramFlags |= (bigramOffset < 0) ? FormatSpec.FLAG_ATTRIBUTE_OFFSET_NEGATIVE : 0; + switch (BinaryDictInputOutput.getByteSize(bigramOffset)) { + case 1: + bigramFlags |= FormatSpec.FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE; + break; + case 2: + bigramFlags |= FormatSpec.FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES; + break; + case 3: + bigramFlags |= FormatSpec.FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES; + break; + } + bigramFlags |= bigramFrequency & FormatSpec.FLAG_ATTRIBUTE_FREQUENCY; + destination.write((byte)bigramFlags); + writeVariableAddress(destination, Math.abs(bigramOffset)); + } + } + } } diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 3e6965a17..ba29523c8 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -153,7 +153,7 @@ public final class BinaryDictInputOutput { * @param character the character code. * @return the size in binary encoded-form, either 1 or 3 bytes. */ - private static int getCharSize(final int character) { + static int getCharSize(final int character) { // See char encoding in FusionDictionary.java if (fitsOnOneByte(character)) return 1; if (FormatSpec.INVALID_CHARACTER == character) return 1; @@ -337,7 +337,7 @@ public final class BinaryDictInputOutput { * This is known in advance and does not change according to position in the file * like address lists do. */ - private static int getShortcutListSize(final ArrayList shortcutList) { + static int getShortcutListSize(final ArrayList shortcutList) { if (null == shortcutList) return 0; int size = FormatSpec.GROUP_SHORTCUT_LIST_SIZE_SIZE; for (final WeightedString shortcut : shortcutList) { @@ -438,7 +438,7 @@ public final class BinaryDictInputOutput { * @param address the address * @return the byte size. */ - private static int getByteSize(final int address) { + static int getByteSize(final int address) { assert(address <= UINT24_MAX); if (!hasChildrenAddress(address)) { return 0; @@ -858,7 +858,7 @@ public final class BinaryDictInputOutput { * @param frequency the frequency of the attribute, 0..15 * @return the flags */ - private static final int makeShortcutFlags(final boolean more, final int frequency) { + static final int makeShortcutFlags(final boolean more, final int frequency) { return (more ? FormatSpec.FLAG_ATTRIBUTE_HAS_NEXT : 0) + (frequency & FormatSpec.FLAG_ATTRIBUTE_FREQUENCY); } @@ -896,6 +896,7 @@ public final class BinaryDictInputOutput { */ private static int writePlacedNode(final FusionDictionary dict, byte[] buffer, final Node node, final FormatOptions formatOptions) { + // TODO: Make the code in common with BinaryDictIOUtils#writeCharGroup int index = node.mCachedAddress; final int groupCount = node.mData.size(); -- cgit v1.2.3-83-g751a From 7f438aa12f683ac15c8c8e60ca852412d00128db Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Mon, 1 Oct 2012 17:29:30 +0900 Subject: Make writeCharGroup return a size of a new group. bug: 6669677 Change-Id: I56f6a07b04b08443f2c052927404318c2018fc9d --- .../latin/makedict/BinaryDictIOUtils.java | 52 ++++++++++++++++++---- 1 file changed, 43 insertions(+), 9 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 5c6417b04..5ed910c50 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -255,23 +255,34 @@ public final class BinaryDictIOUtils { buffer.put((byte)newFlags); } - private static void writeSInt24ToBuffer(final FusionDictionaryBufferInterface buffer, + /** + * @return the size written, in bytes. Always 3 bytes. + */ + private static int writeSInt24ToBuffer(final FusionDictionaryBufferInterface buffer, final int value) { final int absValue = Math.abs(value); buffer.put((byte)(((value < 0 ? 0x80 : 0) | (absValue >> 16)) & 0xFF)); buffer.put((byte)((absValue >> 8) & 0xFF)); buffer.put((byte)(absValue & 0xFF)); + return 3; } - private static void writeSInt24ToStream(final OutputStream destination, final int value) + /** + * @return the size written, in bytes. Always 3 bytes. + */ + private static int writeSInt24ToStream(final OutputStream destination, final int value) throws IOException { final int absValue = Math.abs(value); destination.write((byte)(((value < 0 ? 0x80 : 0) | (absValue >> 16)) & 0xFF)); destination.write((byte)((absValue >> 8) & 0xFF)); destination.write((byte)(absValue & 0xFF)); + return 3; } - private static void writeVariableAddress(final OutputStream destination, final int value) + /** + * @return the size written, in bytes. 1, 2, or 3 bytes. + */ + private static int writeVariableAddress(final OutputStream destination, final int value) throws IOException { switch (BinaryDictInputOutput.getByteSize(value)) { case 1: @@ -287,6 +298,7 @@ public final class BinaryDictIOUtils { destination.write((byte)(0xFF & value)); break; } + return BinaryDictInputOutput.getByteSize(value); } /** @@ -323,20 +335,33 @@ public final class BinaryDictIOUtils { } } - private static void writeString(final OutputStream destination, final String word) + /** + * Write a string to a stream. + * + * @param destination the stream to write. + * @param word the string to be written. + * @return the size written, in bytes. + * @throws IOException + */ + private static int writeString(final OutputStream destination, final String word) throws IOException { + int size = 0; final int length = word.length(); for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) { final int codePoint = word.codePointAt(i); if (CharEncoding.getCharSize(codePoint) == 1) { destination.write((byte)codePoint); + size++; } else { destination.write((byte)(0xFF & (codePoint >> 16))); destination.write((byte)(0xFF & (codePoint >> 8))); destination.write((byte)(0xFF & codePoint)); + size += 3; } } destination.write((byte)FormatSpec.GROUP_CHARACTERS_TERMINATOR); + size++; + return size; } /** @@ -369,27 +394,32 @@ public final class BinaryDictIOUtils { * * @param destination the stream to write. * @param info the char group info to be written. + * @return the size written, in bytes. */ - public static void writeCharGroup(final OutputStream destination, final CharGroupInfo info) + public static int writeCharGroup(final OutputStream destination, final CharGroupInfo info) throws IOException { + int size = 1; destination.write((byte)info.mFlags); final int parentOffset = info.mParentAddress == FormatSpec.NO_PARENT_ADDRESS ? FormatSpec.NO_PARENT_ADDRESS : info.mParentAddress - info.mOriginalAddress; - writeSInt24ToStream(destination, parentOffset); + size += writeSInt24ToStream(destination, parentOffset); for (int i = 0; i < info.mCharacters.length; ++i) { if (CharEncoding.getCharSize(info.mCharacters[i]) == 1) { destination.write((byte)info.mCharacters[i]); + size++; } else { - writeSInt24ToStream(destination, info.mCharacters[i]); + size += writeSInt24ToStream(destination, info.mCharacters[i]); } } if (info.mCharacters.length > 1) { destination.write((byte)FormatSpec.GROUP_CHARACTERS_TERMINATOR); + size++; } if ((info.mFlags & FormatSpec.FLAG_IS_TERMINAL) != 0) { destination.write((byte)info.mFrequency); + size++; } final int childrenOffset = info.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS ? @@ -401,12 +431,14 @@ public final class BinaryDictIOUtils { BinaryDictInputOutput.getShortcutListSize(info.mShortcutTargets); destination.write((byte)(shortcutListSize >> 8)); destination.write((byte)(shortcutListSize & 0xFF)); + size += 2; final Iterator shortcutIterator = info.mShortcutTargets.iterator(); while (shortcutIterator.hasNext()) { final WeightedString target = shortcutIterator.next(); destination.write((byte)BinaryDictInputOutput.makeShortcutFlags( shortcutIterator.hasNext(), target.mFrequency)); - writeString(destination, target.mWord); + size++; + size += writeString(destination, target.mWord); } } @@ -432,8 +464,10 @@ public final class BinaryDictIOUtils { } bigramFlags |= bigramFrequency & FormatSpec.FLAG_ATTRIBUTE_FREQUENCY; destination.write((byte)bigramFlags); - writeVariableAddress(destination, Math.abs(bigramOffset)); + size++; + size += writeVariableAddress(destination, Math.abs(bigramOffset)); } } + return size; } } -- cgit v1.2.3-83-g751a From 15281adbc1580262888aba6fc73bbbe7fa9e0de8 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Tue, 2 Oct 2012 10:30:03 +0900 Subject: Show gesture floating preview text by default Bug: 7244214 Change-Id: Ib4ab810ef50798828dd10c39a8077466165772e4 --- java/res/xml/prefs.xml | 4 ++-- .../com/android/inputmethod/keyboard/KeyboardView.java | 15 +++++++++++++-- java/src/com/android/inputmethod/latin/Settings.java | 8 ++++---- .../src/com/android/inputmethod/latin/SettingsValues.java | 2 +- 4 files changed, 20 insertions(+), 9 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml index fe82b327c..9172b2415 100644 --- a/java/res/xml/prefs.xml +++ b/java/res/xml/prefs.xml @@ -88,11 +88,11 @@ android:persistent="true" android:defaultValue="true" /> + android:defaultValue="true" /> Date: Tue, 2 Oct 2012 17:09:56 +0900 Subject: Avoid calling switchToLastInputMethod when other IMEs are in effect Bug: 7268389 Change-Id: I4d960cbf063002b4dc0ea813c966366b56c0346d --- java/src/com/android/inputmethod/latin/LatinIME.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 311355374..494846b04 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1219,22 +1219,25 @@ public final class LatinIME extends InputMethodService implements KeyboardAction mConnection.performEditorAction(actionId); } + // TODO: Revise the language switch key behavior to make it much smarter and more reasonable. private void handleLanguageSwitchKey() { - final boolean includesOtherImes = mCurrentSettings.mIncludesOtherImesInLanguageSwitchList; final IBinder token = getWindow().getWindow().getAttributes().token; + if (mCurrentSettings.mIncludesOtherImesInLanguageSwitchList) { + mImm.switchToNextInputMethod(token, false /* onlyCurrentIme */); + return; + } if (mShouldSwitchToLastSubtype) { final InputMethodSubtype lastSubtype = mImm.getLastInputMethodSubtype(); final boolean lastSubtypeBelongsToThisIme = ImfUtils.checkIfSubtypeBelongsToThisImeAndEnabled(this, lastSubtype); - if ((includesOtherImes || lastSubtypeBelongsToThisIme) - && mImm.switchToLastInputMethod(token)) { + if (lastSubtypeBelongsToThisIme && mImm.switchToLastInputMethod(token)) { mShouldSwitchToLastSubtype = false; } else { - mImm.switchToNextInputMethod(token, !includesOtherImes); + mImm.switchToNextInputMethod(token, true /* onlyCurrentIme */); mShouldSwitchToLastSubtype = true; } } else { - mImm.switchToNextInputMethod(token, !includesOtherImes); + mImm.switchToNextInputMethod(token, true /* onlyCurrentIme */); } } -- cgit v1.2.3-83-g751a From d445b56ce14152b30143302899790af255691148 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Wed, 3 Oct 2012 13:01:52 +0900 Subject: Fix possible NPE caused while monkey test Bug: 7269036 Change-Id: I9054b33ad3c8996cac3ee5f0e9c01ba8ceea4971 --- .../android/inputmethod/keyboard/KeyboardSwitcher.java | 6 +++++- java/src/com/android/inputmethod/latin/LatinIME.java | 8 ++++++-- .../com/android/inputmethod/latin/WordComposer.java | 18 ++++++++++-------- 3 files changed, 21 insertions(+), 11 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index 88d7b667f..e99e956e2 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -390,7 +390,11 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { } public int getManualCapsMode() { - switch (getKeyboard().mId.mElementId) { + final Keyboard keyboard = getKeyboard(); + if (keyboard == null) { + return WordComposer.CAPS_MODE_OFF; + } + switch (keyboard.mId.mElementId) { case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED: case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: return WordComposer.CAPS_MODE_MANUAL_SHIFT_LOCKED; diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 311355374..fe6ad4901 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1910,6 +1910,10 @@ public final class LatinIME extends InputMethodService implements KeyboardAction } private SuggestedWords getSuggestedWords(final int sessionId) { + final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); + if (keyboard == null) { + return SuggestedWords.EMPTY; + } final String typedWord = mWordComposer.getTypedWord(); // Get the word on which we should search the bigrams. If we are composing a word, it's // whatever is *before* the half-committed word in the buffer, hence 2; if we aren't, we @@ -1919,8 +1923,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction mConnection.getNthPreviousWord(mCurrentSettings.mWordSeparators, mWordComposer.isComposingWord() ? 2 : 1); final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer, - prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), - mCurrentSettings.mCorrectionEnabled, sessionId); + prevWord, keyboard.getProximityInfo(), mCurrentSettings.mCorrectionEnabled, + sessionId); return maybeRetrieveOlderSuggestions(typedWord, suggestedWords); } diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index 8a1bbed12..da0071adc 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -177,14 +177,16 @@ public final class WordComposer { * Internal method to retrieve reasonable proximity info for a character. */ private void addKeyInfo(final int codePoint, final Keyboard keyboard) { - final Key key = keyboard.getKey(codePoint); - if (key != null) { - final int x = key.mX + key.mWidth / 2; - final int y = key.mY + key.mHeight / 2; - add(codePoint, x, y); - return; + final int x, y; + final Key key; + if (keyboard != null && (key = keyboard.getKey(codePoint)) != null) { + x = key.mX + key.mWidth / 2; + y = key.mY + key.mHeight / 2; + } else { + x = Constants.NOT_A_COORDINATE; + y = Constants.NOT_A_COORDINATE; } - add(codePoint, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); + add(codePoint, x, y); } /** @@ -195,7 +197,7 @@ public final class WordComposer { reset(); final int length = word.length(); for (int i = 0; i < length; i = Character.offsetByCodePoints(word, i, 1)) { - int codePoint = Character.codePointAt(word, i); + final int codePoint = Character.codePointAt(word, i); addKeyInfo(codePoint, keyboard); } mIsResumed = true; -- cgit v1.2.3-83-g751a From 4ad4ff618f5102148d73e3c04d809942bcf16f86 Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Wed, 3 Oct 2012 12:34:52 +0900 Subject: Add makeCharGroupFlags. Change-Id: Id2c580f21b77f66a97c5fbdf4542fdafe6c43614 --- .../latin/makedict/BinaryDictInputOutput.java | 89 ++++++++++++---------- .../inputmethod/latin/makedict/FormatSpec.java | 12 ++- 2 files changed, 57 insertions(+), 44 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index ba29523c8..136c0c43f 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -720,53 +720,60 @@ public final class BinaryDictInputOutput { return 3; } - private static byte makeCharGroupFlags(final CharGroup group, final int groupAddress, - final int childrenOffset, final FormatOptions formatOptions) { + /** + * Makes the flag value for a char group. + * + * @param hasMultipleChars whether the group has multiple chars. + * @param isTerminal whether the group is terminal. + * @param childrenAddressSize the size of a children address. + * @param hasShortcuts whether the group has shortcuts. + * @param hasBigrams whether the group has bigrams. + * @param isNotAWord whether the group is not a word. + * @param isBlackListEntry whether the group is a blacklist entry. + * @param formatOptions file format options. + * @return the flags + */ + static int makeCharGroupFlags(final boolean hasMultipleChars, final boolean isTerminal, + final int childrenAddressSize, final boolean hasShortcuts, final boolean hasBigrams, + final boolean isNotAWord, final boolean isBlackListEntry, + final FormatOptions formatOptions) { byte flags = 0; - if (group.mChars.length > 1) flags |= FormatSpec.FLAG_HAS_MULTIPLE_CHARS; - if (group.mFrequency >= 0) { - flags |= FormatSpec.FLAG_IS_TERMINAL; - } - if (null != group.mChildren) { - final int byteSize = formatOptions.mSupportsDynamicUpdate - ? FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE : getByteSize(childrenOffset); - switch (byteSize) { - case 1: - flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_ONEBYTE; - break; - case 2: - flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_TWOBYTES; - break; - case 3: - flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_THREEBYTES; - break; - default: - throw new RuntimeException("Node with a strange address"); - } - } else if (formatOptions.mSupportsDynamicUpdate) { - flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_THREEBYTES; - } - if (null != group.mShortcutTargets) { - if (DBG && 0 == group.mShortcutTargets.size()) { - throw new RuntimeException("0-sized shortcut list must be null"); - } - flags |= FormatSpec.FLAG_HAS_SHORTCUT_TARGETS; - } - if (null != group.mBigrams) { - if (DBG && 0 == group.mBigrams.size()) { - throw new RuntimeException("0-sized bigram list must be null"); + if (hasMultipleChars) flags |= FormatSpec.FLAG_HAS_MULTIPLE_CHARS; + if (isTerminal) flags |= FormatSpec.FLAG_IS_TERMINAL; + if (formatOptions.mSupportsDynamicUpdate) { + flags |= FormatSpec.FLAG_IS_NOT_MOVED; + } else if (true) { + switch (childrenAddressSize) { + case 1: + flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_ONEBYTE; + break; + case 2: + flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_TWOBYTES; + break; + case 3: + flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_THREEBYTES; + break; + case 0: + flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_NOADDRESS; + break; + default: + throw new RuntimeException("Node with a strange address"); } - flags |= FormatSpec.FLAG_HAS_BIGRAMS; - } - if (group.mIsNotAWord) { - flags |= FormatSpec.FLAG_IS_NOT_A_WORD; - } - if (group.mIsBlacklistEntry) { - flags |= FormatSpec.FLAG_IS_BLACKLISTED; } + if (hasShortcuts) flags |= FormatSpec.FLAG_HAS_SHORTCUT_TARGETS; + if (hasBigrams) flags |= FormatSpec.FLAG_HAS_BIGRAMS; + if (isNotAWord) flags |= FormatSpec.FLAG_IS_NOT_A_WORD; + if (isBlackListEntry) flags |= FormatSpec.FLAG_IS_BLACKLISTED; return flags; } + private static byte makeCharGroupFlags(final CharGroup group, final int groupAddress, + final int childrenOffset, final FormatOptions formatOptions) { + return (byte) makeCharGroupFlags(group.mChars.length > 1, group.mFrequency >= 0, + getByteSize(childrenOffset), group.mShortcutTargets != null, group.mBigrams != null, + group.mIsNotAWord, group.mIsBlacklistEntry, formatOptions); + } + /** * Makes the flag value for a bigram. * diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index b3fbb9fb5..5ef35a1cc 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -59,8 +59,9 @@ public final class FormatSpec { * l | 10 = 2 bytes : FLAG_GROUP_ADDRESS_TYPE_TWOBYTES * a | 11 = 3 bytes : FLAG_GROUP_ADDRESS_TYPE_THREEBYTES * g | ELSE - * s | is moved ? 2 bits, 11 = no - * | 01 = yes + * s | is moved ? 2 bits, 11 = no : FLAG_IS_NOT_MOVED + * | This must be the same as FLAG_GROUP_ADDRESS_TYPE_THREEBYTES + * | 01 = yes : FLAG_IS_MOVED * | the new address is stored in the same place as the parent address * | has several chars ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_MULTIPLE_CHARS * | has a terminal ? 1 bit, 1 = yes, 0 = no : FLAG_IS_TERMINAL @@ -170,6 +171,7 @@ public final class FormatSpec { static final int PARENT_ADDRESS_SIZE = 3; static final int FORWARD_LINK_ADDRESS_SIZE = 3; + // These flags are used only in the static dictionary. static final int MASK_GROUP_ADDRESS_TYPE = 0xC0; static final int FLAG_GROUP_ADDRESS_TYPE_NOADDRESS = 0x00; static final int FLAG_GROUP_ADDRESS_TYPE_ONEBYTE = 0x40; @@ -183,7 +185,11 @@ public final class FormatSpec { static final int FLAG_HAS_BIGRAMS = 0x04; static final int FLAG_IS_NOT_A_WORD = 0x02; static final int FLAG_IS_BLACKLISTED = 0x01; - static final int FLAG_IS_MOVED = 0x40; + + // These flags are used only in the dynamic dictionary. + static final int FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE = 0x40; + static final int FLAG_IS_MOVED = 0x00 | FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE; + static final int FLAG_IS_NOT_MOVED = 0x80 | FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE; static final int FLAG_ATTRIBUTE_HAS_NEXT = 0x80; static final int FLAG_ATTRIBUTE_OFFSET_NEGATIVE = 0x40; -- cgit v1.2.3-83-g751a From 3e5a3c18bebbfb56012383411b24ee81ffde09cb Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Wed, 3 Oct 2012 14:46:47 +0900 Subject: Add final modifier to the classes under suggestions sub-package Change-Id: I19fc8eaac1aebef9cf4deb004e78484ff9a1e7ca --- .../latin/suggestions/MoreSuggestionsView.java | 28 +++---- .../latin/suggestions/SuggestionStripView.java | 88 ++++++++++++---------- 2 files changed, 62 insertions(+), 54 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java index 9b9a35478..740476f62 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java @@ -56,17 +56,17 @@ public final class MoreSuggestionsView extends KeyboardView implements MoreKeysP final KeyboardActionListener mSuggestionsPaneListener = new KeyboardActionListener.Adapter() { @Override - public void onPressKey(int primaryCode) { + public void onPressKey(final int primaryCode) { mListener.onPressKey(primaryCode); } @Override - public void onReleaseKey(int primaryCode, boolean withSliding) { + public void onReleaseKey(final int primaryCode, final boolean withSliding) { mListener.onReleaseKey(primaryCode, withSliding); } @Override - public void onCodeInput(int primaryCode, int x, int y) { + public void onCodeInput(final int primaryCode, final int x, final int y) { final int index = primaryCode - MoreSuggestions.SUGGESTION_CODE_BASE; if (index >= 0 && index < SuggestionStripView.MAX_SUGGESTIONS) { mListener.onCustomRequest(index); @@ -79,11 +79,12 @@ public final class MoreSuggestionsView extends KeyboardView implements MoreKeysP } }; - public MoreSuggestionsView(Context context, AttributeSet attrs) { + public MoreSuggestionsView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.moreSuggestionsViewStyle); } - public MoreSuggestionsView(Context context, AttributeSet attrs, int defStyle) { + public MoreSuggestionsView(final Context context, final AttributeSet attrs, + final int defStyle) { super(context, attrs, defStyle); final Resources res = context.getResources(); @@ -94,7 +95,7 @@ public final class MoreSuggestionsView extends KeyboardView implements MoreKeysP } @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Keyboard keyboard = getKeyboard(); if (keyboard != null) { final int width = keyboard.mOccupiedWidth + getPaddingLeft() + getPaddingRight(); @@ -106,7 +107,7 @@ public final class MoreSuggestionsView extends KeyboardView implements MoreKeysP } @Override - public void setKeyboard(Keyboard keyboard) { + public void setKeyboard(final Keyboard keyboard) { super.setKeyboard(keyboard); mModalPanelKeyDetector.setKeyboard(keyboard, -getPaddingLeft(), -getPaddingTop()); mSlidingPanelKeyDetector.setKeyboard(keyboard, -getPaddingLeft(), @@ -134,15 +135,16 @@ public final class MoreSuggestionsView extends KeyboardView implements MoreKeysP } @Override - public void setKeyPreviewPopupEnabled(boolean previewEnabled, int delay) { + public void setKeyPreviewPopupEnabled(final boolean previewEnabled, final int delay) { // Suggestions pane needs no pop-up key preview displayed, so we pass always false with a // delay of 0. The delay does not matter actually since the popup is not shown anyway. super.setKeyPreviewPopupEnabled(false, 0); } @Override - public void showMoreKeysPanel(View parentView, Controller controller, int pointX, int pointY, - PopupWindow window, KeyboardActionListener listener) { + public void showMoreKeysPanel(final View parentView, final Controller controller, + final int pointX, final int pointY, final PopupWindow window, + final KeyboardActionListener listener) { mController = controller; mListener = listener; final View container = (View)getParent(); @@ -175,12 +177,12 @@ public final class MoreSuggestionsView extends KeyboardView implements MoreKeysP } @Override - public int translateX(int x) { + public int translateX(final int x) { return x - mOriginX; } @Override - public int translateY(int y) { + public int translateY(final int y) { return y - mOriginY; } @@ -207,7 +209,7 @@ public final class MoreSuggestionsView extends KeyboardView implements MoreKeysP }; @Override - public boolean onTouchEvent(MotionEvent me) { + public boolean onTouchEvent(final MotionEvent me) { final int action = me.getAction(); final long eventTime = me.getEventTime(); final int index = me.getActionIndex(); diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index 94283f242..d978c371a 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -85,7 +85,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick static final boolean DBG = LatinImeLogger.sDBG; private final ViewGroup mSuggestionsStrip; - private KeyboardView mKeyboardView; + KeyboardView mKeyboardView; private final View mMoreSuggestionsContainer; private final MoreSuggestionsView mMoreSuggestionsView; @@ -99,8 +99,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick private final PopupWindow mPreviewPopup; private final TextView mPreviewText; - private Listener mListener; - private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY; + Listener mListener; + SuggestedWords mSuggestedWords = SuggestedWords.EMPTY; private final SuggestionStripViewParams mParams; private static final float MIN_TEXT_XSCALE = 0.70f; @@ -110,12 +110,12 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick private static final class UiHandler extends StaticInnerHandlerWrapper { private static final int MSG_HIDE_PREVIEW = 0; - public UiHandler(SuggestionStripView outerInstance) { + public UiHandler(final SuggestionStripView outerInstance) { super(outerInstance); } @Override - public void dispatchMessage(Message msg) { + public void dispatchMessage(final Message msg) { final SuggestionStripView suggestionStripView = getOuterInstance(); switch (msg.what) { case MSG_HIDE_PREVIEW: @@ -179,8 +179,9 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick private final TextView mLeftwardsArrowView; private final TextView mHintToSaveView; - public SuggestionStripViewParams(Context context, AttributeSet attrs, int defStyle, - ArrayList words, ArrayList dividers, ArrayList infos) { + public SuggestionStripViewParams(final Context context, final AttributeSet attrs, + final int defStyle, final ArrayList words, final ArrayList dividers, + final ArrayList infos) { mWords = words; mDividers = dividers; mInfos = infos; @@ -252,7 +253,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick return mMaxMoreSuggestionsRow * mMoreSuggestionsRowHeight + mMoreSuggestionsBottomGap; } - public int setMoreSuggestionsHeight(int remainingHeight) { + public int setMoreSuggestionsHeight(final int remainingHeight) { final int currentHeight = getMoreSuggestionsHeight(); if (currentHeight <= remainingHeight) { return currentHeight; @@ -264,7 +265,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick return newHeight; } - private static Drawable getMoreSuggestionsHint(Resources res, float textSize, int color) { + private static Drawable getMoreSuggestionsHint(final Resources res, final float textSize, + final int color) { final Paint paint = new Paint(); paint.setAntiAlias(true); paint.setTextAlign(Align.CENTER); @@ -281,7 +283,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick return new BitmapDrawable(res, buffer); } - private CharSequence getStyledSuggestionWord(SuggestedWords suggestedWords, int pos) { + private CharSequence getStyledSuggestionWord(final SuggestedWords suggestedWords, + final int pos) { final CharSequence word = suggestedWords.getWord(pos); final boolean isAutoCorrect = pos == 1 && suggestedWords.willAutoCorrect(); final boolean isTypedWordValid = pos == 0 && suggestedWords.mTypedWordValid; @@ -301,7 +304,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick return spannedWord; } - private int getWordPosition(int index, SuggestedWords suggestedWords) { + private int getWordPosition(final int index, final SuggestedWords suggestedWords) { // TODO: This works for 3 suggestions. Revisit this algorithm when there are 5 or more // suggestions. final int centerPos = suggestedWords.willAutoCorrect() ? 1 : 0; @@ -314,7 +317,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick } } - private int getSuggestionTextColor(int index, SuggestedWords suggestedWords, int pos) { + private int getSuggestionTextColor(final int index, final SuggestedWords suggestedWords, + final int pos) { // TODO: Need to revisit this logic with bigram suggestions final boolean isSuggested = (pos != 0); @@ -357,8 +361,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick params.gravity = Gravity.CENTER; } - public void layout(SuggestedWords suggestedWords, ViewGroup stripView, ViewGroup placer, - int stripWidth) { + public void layout(final SuggestedWords suggestedWords, final ViewGroup stripView, + final ViewGroup placer, final int stripWidth) { if (suggestedWords.mIsPunctuationSuggestions) { layoutPunctuationSuggestions(suggestedWords, stripView); return; @@ -420,14 +424,14 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick } } - private int getSuggestionWidth(int index, int maxWidth) { + private int getSuggestionWidth(final int index, final int maxWidth) { final int paddings = mPadding * mSuggestionsCountInStrip; final int dividers = mDividerWidth * (mSuggestionsCountInStrip - 1); final int availableWidth = maxWidth - paddings - dividers; return (int)(availableWidth * getSuggestionWeight(index)); } - private float getSuggestionWeight(int index) { + private float getSuggestionWeight(final int index) { if (index == mCenterSuggestionIndex) { return mCenterSuggestionWeight; } else { @@ -436,7 +440,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick } } - private void setupTexts(SuggestedWords suggestedWords, int countInStrip) { + private void setupTexts(final SuggestedWords suggestedWords, final int countInStrip) { mTexts.clear(); final int count = Math.min(suggestedWords.size(), countInStrip); for (int pos = 0; pos < count; pos++) { @@ -449,8 +453,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick } } - private void layoutPunctuationSuggestions(SuggestedWords suggestedWords, - ViewGroup stripView) { + private void layoutPunctuationSuggestions(final SuggestedWords suggestedWords, + final ViewGroup stripView) { final int countInStrip = Math.min(suggestedWords.size(), PUNCTUATIONS_IN_STRIP); for (int index = 0; index < countInStrip; index++) { if (index != 0) { @@ -471,8 +475,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick mMoreSuggestionsAvailable = false; } - public void layoutAddToDictionaryHint(CharSequence word, ViewGroup stripView, - int stripWidth, CharSequence hintText, OnClickListener listener) { + public void layoutAddToDictionaryHint(final CharSequence word, final ViewGroup stripView, + final int stripWidth, final CharSequence hintText, final OnClickListener listener) { final int width = stripWidth - mDividerWidth - mPadding * 2; final TextView wordView = mWordToSaveView; @@ -513,11 +517,11 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick return (CharSequence)mWordToSaveView.getTag(); } - public boolean isAddToDictionaryShowing(View v) { + public boolean isAddToDictionaryShowing(final View v) { return v == mWordToSaveView || v == mHintToSaveView || v == mLeftwardsArrowView; } - private static void setLayoutWeight(View v, float weight, int height) { + private static void setLayoutWeight(final View v, final float weight, final int height) { final ViewGroup.LayoutParams lp = v.getLayoutParams(); if (lp instanceof LinearLayout.LayoutParams) { final LinearLayout.LayoutParams llp = (LinearLayout.LayoutParams)lp; @@ -527,7 +531,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick } } - private static float getTextScaleX(CharSequence text, int maxWidth, TextPaint paint) { + private static float getTextScaleX(final CharSequence text, final int maxWidth, + final TextPaint paint) { paint.setTextScaleX(1.0f); final int width = getTextWidth(text, paint); if (width <= maxWidth) { @@ -536,8 +541,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick return maxWidth / (float)width; } - private static CharSequence getEllipsizedText(CharSequence text, int maxWidth, - TextPaint paint) { + private static CharSequence getEllipsizedText(final CharSequence text, final int maxWidth, + final TextPaint paint) { if (text == null) return null; paint.setTextScaleX(1.0f); final int width = getTextWidth(text, paint); @@ -558,7 +563,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick return ellipsized; } - private static int getTextWidth(CharSequence text, TextPaint paint) { + private static int getTextWidth(final CharSequence text, final TextPaint paint) { if (TextUtils.isEmpty(text)) return 0; final Typeface savedTypeface = paint.getTypeface(); paint.setTypeface(getTextTypeface(text)); @@ -573,7 +578,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick return width; } - private static Typeface getTextTypeface(CharSequence text) { + private static Typeface getTextTypeface(final CharSequence text) { if (!(text instanceof SpannableString)) return Typeface.DEFAULT; @@ -595,11 +600,12 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick * @param context * @param attrs */ - public SuggestionStripView(Context context, AttributeSet attrs) { + public SuggestionStripView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.suggestionStripViewStyle); } - public SuggestionStripView(Context context, AttributeSet attrs, int defStyle) { + public SuggestionStripView(final Context context, final AttributeSet attrs, + final int defStyle) { super(context, attrs, defStyle); final LayoutInflater inflater = LayoutInflater.from(context); @@ -660,12 +666,12 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick * A connection back to the input method. * @param listener */ - public void setListener(Listener listener, View inputView) { + public void setListener(final Listener listener, final View inputView) { mListener = listener; mKeyboardView = (KeyboardView)inputView.findViewById(R.id.keyboard_view); } - public void setSuggestions(SuggestedWords suggestedWords) { + public void setSuggestions(final SuggestedWords suggestedWords) { if (suggestedWords == null) return; @@ -677,7 +683,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick } } - public int setMoreSuggestionsHeight(int remainingHeight) { + public int setMoreSuggestionsHeight(final int remainingHeight) { return mParams.setMoreSuggestionsHeight(remainingHeight); } @@ -686,7 +692,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick && mParams.isAddToDictionaryShowing(mSuggestionsStrip.getChildAt(0)); } - public void showAddToDictionaryHint(CharSequence word, CharSequence hintText) { + public void showAddToDictionaryHint(final CharSequence word, final CharSequence hintText) { clear(); mParams.layoutAddToDictionaryHint(word, mSuggestionsStrip, getWidth(), hintText, this); } @@ -710,14 +716,14 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick dismissMoreSuggestions(); } - private void hidePreview() { + void hidePreview() { mPreviewPopup.dismiss(); } private final KeyboardActionListener mMoreSuggestionsListener = new KeyboardActionListener.Adapter() { @Override - public boolean onCustomRequest(int requestCode) { + public boolean onCustomRequest(final int requestCode) { final int index = requestCode; final CharSequence word = mSuggestedWords.getWord(index); mListener.pickSuggestionManually(index, word); @@ -739,7 +745,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick } }; - private boolean dismissMoreSuggestions() { + boolean dismissMoreSuggestions() { if (mMoreSuggestionsWindow.isShowing()) { mMoreSuggestionsWindow.dismiss(); return true; @@ -748,11 +754,11 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick } @Override - public boolean onLongClick(View view) { + public boolean onLongClick(final View view) { return showMoreSuggestions(); } - private boolean showMoreSuggestions() { + boolean showMoreSuggestions() { final Keyboard parentKeyboard = KeyboardSwitcher.getInstance().getKeyboard(); if (parentKeyboard == null) { return false; @@ -810,7 +816,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick }; @Override - public boolean dispatchTouchEvent(MotionEvent me) { + public boolean dispatchTouchEvent(final MotionEvent me) { if (!mMoreSuggestionsWindow.isShowing() || mMoreSuggestionsMode == MORE_SUGGESTIONS_IN_MODAL_MODE) { mLastX = (int)me.getX(); @@ -852,7 +858,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick } @Override - public void onClick(View view) { + public void onClick(final View view) { if (mParams.isAddToDictionaryShowing(view)) { mListener.addWordToUserDictionary(mParams.getAddToDictionaryWord().toString()); clear(); -- cgit v1.2.3-83-g751a From c6ff7c42d9aeafe2b2d21a34be10f1e9a450153a Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Wed, 3 Oct 2012 14:06:44 +0900 Subject: Add SuggestedWords.isEmpty() method Change-Id: I0fcb104a6a81aee4b99f5ee848eba7495630dc7d --- .../inputmethod/compat/SuggestionSpanUtils.java | 4 ++-- java/src/com/android/inputmethod/latin/LatinIME.java | 20 ++++++++------------ .../android/inputmethod/latin/SuggestedWords.java | 4 ++++ .../latin/suggestions/SuggestionStripView.java | 3 --- 4 files changed, 14 insertions(+), 17 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java index 159f43650..9a89eedd0 100644 --- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java +++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java @@ -108,8 +108,8 @@ public final class SuggestionSpanUtils { CharSequence pickedWord, SuggestedWords suggestedWords, boolean dictionaryAvailable) { if (!dictionaryAvailable || TextUtils.isEmpty(pickedWord) || CONSTRUCTOR_SuggestionSpan == null - || suggestedWords == null || suggestedWords.size() == 0 - || suggestedWords.mIsPrediction || suggestedWords.mIsPunctuationSuggestions + || suggestedWords.isEmpty() || suggestedWords.mIsPrediction + || suggestedWords.mIsPunctuationSuggestions || OBJ_SUGGESTIONS_MAX_SIZE == null) { return pickedWord; } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 69a4fa63c..c0938cf97 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1518,8 +1518,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction private void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords, final boolean dismissGestureFloatingPreviewText) { - final String batchInputText = (suggestedWords.size() > 0) - ? suggestedWords.getWord(0) : null; + final String batchInputText = suggestedWords.isEmpty() + ? null : suggestedWords.getWord(0); final KeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); mainKeyboardView.showGestureFloatingPreviewText(batchInputText); showSuggestionStrip(suggestedWords, null); @@ -1537,8 +1537,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction public void onEndBatchInput(final InputPointers batchPointers) { final SuggestedWords suggestedWords = BatchInputUpdater.getInstance().onEndBatchInput( batchPointers, this); - final String batchInputText = (suggestedWords.size() > 0) - ? suggestedWords.getWord(0) : null; + final String batchInputText = suggestedWords.isEmpty() + ? null : suggestedWords.getWord(0); if (TextUtils.isEmpty(batchInputText)) { return; } @@ -1963,19 +1963,15 @@ public final class LatinIME extends InputMethodService implements KeyboardAction private void showSuggestionStrip(final SuggestedWords suggestedWords, final CharSequence typedWord) { - if (null == suggestedWords || suggestedWords.size() <= 0) { + if (suggestedWords.isEmpty()) { clearSuggestionStrip(); return; } final CharSequence autoCorrection; - if (suggestedWords.size() > 0) { - if (suggestedWords.mWillAutoCorrect) { - autoCorrection = suggestedWords.getWord(1); - } else { - autoCorrection = typedWord; - } + if (suggestedWords.mWillAutoCorrect) { + autoCorrection = suggestedWords.getWord(1); } else { - autoCorrection = null; + autoCorrection = typedWord; } mWordComposer.setAutoCorrection(autoCorrection); final boolean isAutoCorrection = suggestedWords.willAutoCorrect(); diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index 52e292a86..ad94affb2 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -53,6 +53,10 @@ public final class SuggestedWords { mIsPrediction = isPrediction; } + public boolean isEmpty() { + return mSuggestedWordInfoList.isEmpty(); + } + public int size() { return mSuggestedWordInfoList.size(); } diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index d978c371a..6056af95c 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -672,9 +672,6 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick } public void setSuggestions(final SuggestedWords suggestedWords) { - if (suggestedWords == null) - return; - clear(); mSuggestedWords = suggestedWords; mParams.layout(mSuggestedWords, mSuggestionsStrip, this, getWidth()); -- cgit v1.2.3-83-g751a From 66d955ad711d4a1248157056a1d3d643af19fd3f Mon Sep 17 00:00:00 2001 From: Satoshi Kataoka Date: Wed, 3 Oct 2012 17:15:47 +0900 Subject: Throw illegal argument exception in BinaryDictionary::editDistance Bug: 7276803 Change-Id: Icd9bdec0a04179a29d00336819d205627f77b71a --- java/src/com/android/inputmethod/latin/BinaryDictionary.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index e084cb306..7184f1d8a 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -187,6 +187,9 @@ public final class BinaryDictionary extends Dictionary { } public static int editDistance(String before, String after) { + if (before == null || after == null) { + throw new IllegalArgumentException(); + } return editDistanceNative(before.toCharArray(), after.toCharArray()); } -- cgit v1.2.3-83-g751a From 7223cc2ef1d7fd4ad4ab62166114b36ce7313c55 Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Wed, 3 Oct 2012 14:59:27 +0900 Subject: Add MAX_BIGRAMS_IN_A_GROUP. Change-Id: I128d5deb8e523045d7ad77d7a8fd3db944f71238 --- .../android/inputmethod/latin/makedict/BinaryDictInputOutput.java | 6 +++++- java/src/com/android/inputmethod/latin/makedict/FormatSpec.java | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 136c0c43f..14fc36681 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -1297,7 +1297,8 @@ public final class BinaryDictInputOutput { ArrayList bigrams = null; if (0 != (flags & FormatSpec.FLAG_HAS_BIGRAMS)) { bigrams = new ArrayList(); - while (true) { + int bigramCount = 0; + while (bigramCount++ < FormatSpec.MAX_BIGRAMS_IN_A_GROUP) { final int bigramFlags = buffer.readUnsignedByte(); ++addressPointer; final int sign = 0 == (bigramFlags & FormatSpec.FLAG_ATTRIBUTE_OFFSET_NEGATIVE) @@ -1325,6 +1326,9 @@ public final class BinaryDictInputOutput { bigramAddress)); if (0 == (bigramFlags & FormatSpec.FLAG_ATTRIBUTE_HAS_NEXT)) break; } + if (bigramCount >= FormatSpec.MAX_BIGRAMS_IN_A_GROUP) { + MakedictLog.d("too many bigrams in a group."); + } } return new CharGroupInfo(originalGroupAddress, addressPointer, flags, characters, frequency, parentAddress, childrenAddress, shortcutTargets, bigrams); diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index 5ef35a1cc..3fd9e4037 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -216,6 +216,7 @@ public final class FormatSpec { static final int MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT = 0x7F; // 127 static final int MAX_CHARGROUPS_IN_A_NODE = 0x7FFF; // 32767 + static final int MAX_BIGRAMS_IN_A_GROUP = 10000; static final int MAX_TERMINAL_FREQUENCY = 255; static final int MAX_BIGRAM_FREQUENCY = 15; -- cgit v1.2.3-83-g751a From a853356b82e2dc74962243e3143c0ff7a33f3c20 Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Wed, 3 Oct 2012 17:23:39 +0900 Subject: Add isDeletedGroup. Change-Id: I83f09c068868e5e6e1b46f494a6ef957f0b466d8 --- .../latin/makedict/BinaryDictIOUtils.java | 29 ++++++++++++++-------- .../latin/makedict/BinaryDictInputOutput.java | 8 ++++++ .../inputmethod/latin/makedict/FormatSpec.java | 2 ++ 3 files changed, 29 insertions(+), 10 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 5ed910c50..7faad78c4 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -95,7 +95,9 @@ public final class BinaryDictIOUtils { final boolean isMovedGroup = BinaryDictInputOutput.isMovedGroup(info.mFlags, formatOptions); - if (!isMovedGroup + final boolean isDeletedGroup = BinaryDictInputOutput.isDeletedGroup(info.mFlags, + formatOptions); + if (!isMovedGroup && !isDeletedGroup && info.mFrequency != FusionDictionary.CharGroup.NOT_A_TERMINAL) {// found word words.put(info.mOriginalAddress, new String(pushedChars, 0, index)); frequencies.put(info.mOriginalAddress, info.mFrequency); @@ -179,10 +181,13 @@ public final class BinaryDictIOUtils { final int charGroupPos = buffer.position(); final CharGroupInfo currentInfo = BinaryDictInputOutput.readCharGroup(buffer, buffer.position(), header.mFormatOptions); - if (BinaryDictInputOutput.isMovedGroup(currentInfo.mFlags, - header.mFormatOptions)) { - continue; - } + final boolean isMovedGroup = + BinaryDictInputOutput.isMovedGroup(currentInfo.mFlags, + header.mFormatOptions); + final boolean isDeletedGroup = + BinaryDictInputOutput.isDeletedGroup(currentInfo.mFlags, + header.mFormatOptions); + if (isMovedGroup) continue; boolean same = true; for (int p = 0, j = word.offsetByCodePoints(0, wordPos); p < currentInfo.mCharacters.length; @@ -197,7 +202,8 @@ public final class BinaryDictIOUtils { if (same) { // found the group matches the word. if (wordPos + currentInfo.mCharacters.length == wordLen) { - if (currentInfo.mFrequency == CharGroup.NOT_A_TERMINAL) { + if (currentInfo.mFrequency == CharGroup.NOT_A_TERMINAL + || isDeletedGroup) { return FormatSpec.NOT_VALID_WORD; } else { return charGroupPos; @@ -233,6 +239,10 @@ public final class BinaryDictIOUtils { return FormatSpec.NOT_VALID_WORD; } + private static int markAsDeleted(final int flags) { + return (flags & (~FormatSpec.MASK_GROUP_ADDRESS_TYPE)) | FormatSpec.FLAG_IS_DELETED; + } + /** * Delete the word from the binary file. * @@ -250,9 +260,8 @@ public final class BinaryDictIOUtils { buffer.position(wordPosition); final int flags = buffer.readUnsignedByte(); - final int newFlags = flags ^ FormatSpec.FLAG_IS_TERMINAL; buffer.position(wordPosition); - buffer.put((byte)newFlags); + buffer.put((byte)markAsDeleted(flags)); } /** @@ -302,7 +311,7 @@ public final class BinaryDictIOUtils { } /** - * Update a parent address in a CharGroup that is addressed by groupOriginAddress. + * Update a parent address in a CharGroup that is referred to by groupOriginAddress. * * @param buffer the buffer to write. * @param groupOriginAddress the address of the group. @@ -380,7 +389,7 @@ public final class BinaryDictIOUtils { final int flags = buffer.readUnsignedByte(); final int parentAddress = BinaryDictInputOutput.readParentAddress(buffer, formatOptions); skipString(buffer, (flags & FormatSpec.FLAG_HAS_MULTIPLE_CHARS) != 0); - if ((FormatSpec.FLAG_IS_TERMINAL) != 0) buffer.readUnsignedByte(); + if ((flags & FormatSpec.FLAG_IS_TERMINAL) != 0) buffer.readUnsignedByte(); final int childrenOffset = newChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS ? FormatSpec.NO_CHILDREN_ADDRESS : newChildrenAddress - buffer.position(); writeSInt24ToBuffer(buffer, childrenOffset); diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 14fc36681..b9fd15fa0 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -401,6 +401,14 @@ public final class BinaryDictInputOutput { return options.mSupportsDynamicUpdate && ((flags & FormatSpec.FLAG_IS_MOVED) == 1); } + /** + * Helper method to check whether the group is deleted. + */ + public static boolean isDeletedGroup(final int flags, final FormatOptions formatOptions) { + return formatOptions.mSupportsDynamicUpdate + && ((flags & FormatSpec.MASK_GROUP_ADDRESS_TYPE) == FormatSpec.FLAG_IS_DELETED); + } + /** * Helper method to check whether the dictionary can be updated dynamically. */ diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index 3fd9e4037..ca851c6a9 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -63,6 +63,7 @@ public final class FormatSpec { * | This must be the same as FLAG_GROUP_ADDRESS_TYPE_THREEBYTES * | 01 = yes : FLAG_IS_MOVED * | the new address is stored in the same place as the parent address + * | is deleted? 10 = yes : FLAG_IS_DELETED * | has several chars ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_MULTIPLE_CHARS * | has a terminal ? 1 bit, 1 = yes, 0 = no : FLAG_IS_TERMINAL * | has shortcut targets ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_SHORTCUT_TARGETS @@ -190,6 +191,7 @@ public final class FormatSpec { static final int FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE = 0x40; static final int FLAG_IS_MOVED = 0x00 | FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE; static final int FLAG_IS_NOT_MOVED = 0x80 | FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE; + static final int FLAG_IS_DELETED = 0x80; static final int FLAG_ATTRIBUTE_HAS_NEXT = 0x80; static final int FLAG_ATTRIBUTE_OFFSET_NEGATIVE = 0x40; -- cgit v1.2.3-83-g751a From 38712ff27d8dccd9127cf85c94ee2c6fd91832b5 Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Wed, 3 Oct 2012 17:37:52 +0900 Subject: Add updateParentAddresses. Change-Id: Iac210131b7c003ef363e1138bf22f777a37c6a89 --- .../latin/makedict/BinaryDictIOUtils.java | 76 ++++++++++++++++++++-- .../latin/makedict/BinaryDictInputOutput.java | 2 +- 2 files changed, 72 insertions(+), 6 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 7faad78c4..6210c923e 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -28,7 +28,6 @@ import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Stack; @@ -172,10 +171,7 @@ public final class BinaryDictIOUtils { if (wordPos >= wordLen) return FormatSpec.NOT_VALID_WORD; do { - int groupOffset = buffer.position() - header.mHeaderSize; final int charGroupCount = BinaryDictInputOutput.readCharGroupCount(buffer); - groupOffset += BinaryDictInputOutput.getGroupCountSize(charGroupCount); - boolean foundNextCharGroup = false; for (int i = 0; i < charGroupCount; ++i) { final int charGroupPos = buffer.position(); @@ -217,7 +213,6 @@ public final class BinaryDictIOUtils { buffer.position(currentInfo.mChildrenAddress); break; } - groupOffset = currentInfo.mEndAddress; } // If we found the next char group, it is under the file pointer. @@ -327,11 +322,82 @@ public final class BinaryDictIOUtils { throw new RuntimeException("this file format does not support parent addresses"); } final int flags = buffer.readUnsignedByte(); + if (BinaryDictInputOutput.isMovedGroup(flags, formatOptions)) { + // if the group is moved, the parent address is stored in the destination group. + // We are guaranteed to process the destination group later, so there is no need to + // update anything here. + buffer.position(originalPosition); + return; + } + if (DBG) { + MakedictLog.d("update parent address flags=" + flags + ", " + groupOriginAddress); + } final int parentOffset = newParentAddress - groupOriginAddress; writeSInt24ToBuffer(buffer, parentOffset); buffer.position(originalPosition); } + private static void skipCharGroup(final FusionDictionaryBufferInterface buffer, + final FormatOptions formatOptions) { + final int flags = buffer.readUnsignedByte(); + BinaryDictInputOutput.readParentAddress(buffer, formatOptions); + skipString(buffer, (flags & FormatSpec.FLAG_HAS_MULTIPLE_CHARS) != 0); + BinaryDictInputOutput.readChildrenAddress(buffer, flags, formatOptions); + if ((flags & FormatSpec.FLAG_IS_TERMINAL) != 0) buffer.readUnsignedByte(); + if ((flags & FormatSpec.FLAG_HAS_SHORTCUT_TARGETS) != 0) { + final int shortcutsSize = buffer.readUnsignedShort(); + buffer.position(buffer.position() + shortcutsSize + - FormatSpec.GROUP_SHORTCUT_LIST_SIZE_SIZE); + } + if ((flags & FormatSpec.FLAG_HAS_BIGRAMS) != 0) { + int bigramCount = 0; + while (bigramCount++ < FormatSpec.MAX_BIGRAMS_IN_A_GROUP) { + final int bigramFlags = buffer.readUnsignedByte(); + switch (bigramFlags & FormatSpec.MASK_ATTRIBUTE_ADDRESS_TYPE) { + case FormatSpec.FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE: + buffer.readUnsignedByte(); + break; + case FormatSpec.FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES: + buffer.readUnsignedShort(); + break; + case FormatSpec.FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES: + buffer.readUnsignedInt24(); + break; + } + if ((bigramFlags & FormatSpec.FLAG_ATTRIBUTE_HAS_NEXT) == 0) break; + } + if (bigramCount >= FormatSpec.MAX_BIGRAMS_IN_A_GROUP) { + throw new RuntimeException("Too many bigrams in a group."); + } + } + } + + /** + * Update parent addresses in a Node that is referred to by nodeOriginAddress. + * + * @param buffer the buffer to be modified. + * @param nodeOriginAddress the address of a modified Node. + * @param newParentAddress the address to be written + * @param formatOptions file format options + */ + public static void updateParentAddresses(final FusionDictionaryBufferInterface buffer, + final int nodeOriginAddress, final int newParentAddress, + final FormatOptions formatOptions) { + final int originalPosition = buffer.position(); + buffer.position(nodeOriginAddress); + do { + final int count = BinaryDictInputOutput.readCharGroupCount(buffer); + for (int i = 0; i < count; ++i) { + updateParentAddress(buffer, buffer.position(), newParentAddress, formatOptions); + skipCharGroup(buffer, formatOptions); + } + final int forwardLinkAddress = buffer.readUnsignedInt24(); + buffer.position(forwardLinkAddress); + } while (formatOptions.mSupportsDynamicUpdate + && buffer.position() != FormatSpec.NO_FORWARD_LINK_ADDRESS); + buffer.position(originalPosition); + } + private static void skipString(final FusionDictionaryBufferInterface buffer, final boolean hasMultipleChars) { if (hasMultipleChars) { diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index b9fd15fa0..78171d03c 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -1209,7 +1209,7 @@ public final class BinaryDictInputOutput { } } - private static int readChildrenAddress(final FusionDictionaryBufferInterface buffer, + static int readChildrenAddress(final FusionDictionaryBufferInterface buffer, final int optionFlags, final FormatOptions options) { if (options.mSupportsDynamicUpdate) { final int address = buffer.readUnsignedInt24(); -- cgit v1.2.3-83-g751a From c3a98ca306d5d6a3dfce3585b73f7431dbf90bfc Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Wed, 3 Oct 2012 17:58:22 +0900 Subject: Add writeNode. Change-Id: I088bb6ea43ce0841d725e48b677d429e1155569d --- .../latin/makedict/BinaryDictIOUtils.java | 111 ++++++++++++++++++++- .../latin/makedict/BinaryDictInputOutput.java | 21 +++- .../inputmethod/latin/makedict/FormatSpec.java | 1 + 3 files changed, 124 insertions(+), 9 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 6210c923e..096ca0992 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -33,6 +33,11 @@ import java.util.Stack; public final class BinaryDictIOUtils { private static final boolean DBG = false; + private static final int MAX_JUMPS = 10000; + + private BinaryDictIOUtils() { + // This utility class is not publicly instantiable. + } private static final class Position { public static final int NOT_READ_GROUPCOUNT = -1; @@ -377,8 +382,8 @@ public final class BinaryDictIOUtils { * * @param buffer the buffer to be modified. * @param nodeOriginAddress the address of a modified Node. - * @param newParentAddress the address to be written - * @param formatOptions file format options + * @param newParentAddress the address to be written. + * @param formatOptions file format options. */ public static void updateParentAddresses(final FusionDictionaryBufferInterface buffer, final int nodeOriginAddress, final int newParentAddress, @@ -435,7 +440,7 @@ public final class BinaryDictIOUtils { } } destination.write((byte)FormatSpec.GROUP_CHARACTERS_TERMINATOR); - size++; + size += FormatSpec.GROUP_TERMINATOR_SIZE; return size; } @@ -473,7 +478,7 @@ public final class BinaryDictIOUtils { */ public static int writeCharGroup(final OutputStream destination, final CharGroupInfo info) throws IOException { - int size = 1; + int size = FormatSpec.GROUP_FLAGS_SIZE; destination.write((byte)info.mFlags); final int parentOffset = info.mParentAddress == FormatSpec.NO_PARENT_ADDRESS ? FormatSpec.NO_PARENT_ADDRESS : info.mParentAddress - info.mOriginalAddress; @@ -497,9 +502,15 @@ public final class BinaryDictIOUtils { size++; } + if (DBG) { + MakedictLog.d("writeCharGroup origin=" + info.mOriginalAddress + ", size=" + size + + ", child=" + info.mChildrenAddress + ", characters =" + + new String(info.mCharacters, 0, info.mCharacters.length)); + } final int childrenOffset = info.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS ? - 0 : info.mChildrenAddress - info.mOriginalAddress; + 0 : info.mChildrenAddress - (info.mOriginalAddress + size); writeSInt24ToStream(destination, childrenOffset); + size += FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE; if (info.mShortcutTargets != null && info.mShortcutTargets.size() > 0) { final int shortcutListSize = @@ -545,4 +556,94 @@ public final class BinaryDictIOUtils { } return size; } + + private static void updateForwardLink(final FusionDictionaryBufferInterface buffer, + final int nodeOriginAddress, final int newNodeAddress, + final FormatOptions formatOptions) { + buffer.position(nodeOriginAddress); + int jumpCount = 0; + while (jumpCount++ < MAX_JUMPS) { + final int count = BinaryDictInputOutput.readCharGroupCount(buffer); + for (int i = 0; i < count; ++i) skipCharGroup(buffer, formatOptions); + final int forwardLinkAddress = buffer.readUnsignedInt24(); + if (forwardLinkAddress == FormatSpec.NO_FORWARD_LINK_ADDRESS) { + buffer.position(buffer.position() - FormatSpec.FORWARD_LINK_ADDRESS_SIZE); + writeSInt24ToBuffer(buffer, newNodeAddress); + return; + } + buffer.position(forwardLinkAddress); + } + if (DBG && jumpCount >= MAX_JUMPS) { + throw new RuntimeException("too many jumps, probably a bug."); + } + } + + /** + * Helper method to move a char group to the tail of the file. + */ + private static int moveCharGroup(final OutputStream destination, + final FusionDictionaryBufferInterface buffer, final CharGroupInfo info, + final int nodeOriginAddress, final int oldGroupAddress, + final FormatOptions formatOptions) throws IOException { + updateParentAddress(buffer, oldGroupAddress, buffer.limit() + 1, formatOptions); + buffer.position(oldGroupAddress); + final int currentFlags = buffer.readUnsignedByte(); + buffer.position(oldGroupAddress); + buffer.put((byte)(FormatSpec.FLAG_IS_MOVED | (currentFlags + & (~FormatSpec.MASK_MOVE_AND_DELETE_FLAG)))); + int size = FormatSpec.GROUP_FLAGS_SIZE; + updateForwardLink(buffer, nodeOriginAddress, buffer.limit(), formatOptions); + size += writeNode(destination, new CharGroupInfo[] { info }); + return size; + } + + /** + * Compute the size of the char group. + */ + private static int computeGroupSize(final CharGroupInfo info, + final FormatOptions formatOptions) { + int size = FormatSpec.GROUP_FLAGS_SIZE + FormatSpec.PARENT_ADDRESS_SIZE + + BinaryDictInputOutput.getGroupCharactersSize(info.mCharacters) + + BinaryDictInputOutput.getChildrenAddressSize(info.mFlags, formatOptions); + if ((info.mFlags & FormatSpec.FLAG_IS_TERMINAL) != 0) { + size += FormatSpec.GROUP_FREQUENCY_SIZE; + } + if (info.mShortcutTargets != null && !info.mShortcutTargets.isEmpty()) { + size += BinaryDictInputOutput.getShortcutListSize(info.mShortcutTargets); + } + if (info.mBigrams != null) { + for (final PendingAttribute attr : info.mBigrams) { + size += FormatSpec.GROUP_FLAGS_SIZE; + size += BinaryDictInputOutput.getByteSize(attr.mAddress); + } + } + return size; + } + + /** + * Write a node to the stream. + * + * @param destination the stream to write. + * @param infos groups to be written. + * @return the size written, in bytes. + * @throws IOException + */ + private static int writeNode(final OutputStream destination, final CharGroupInfo[] infos) + throws IOException { + int size = BinaryDictInputOutput.getGroupCountSize(infos.length); + switch (BinaryDictInputOutput.getGroupCountSize(infos.length)) { + case 1: + destination.write((byte)infos.length); + break; + case 2: + destination.write((byte)(infos.length >> 8)); + destination.write((byte)(infos.length & 0xFF)); + break; + default: + throw new RuntimeException("Invalid group count size."); + } + for (final CharGroupInfo info : infos) size += writeCharGroup(destination, info); + writeSInt24ToStream(destination, FormatSpec.NO_FORWARD_LINK_ADDRESS); + return size + FormatSpec.FORWARD_LINK_ADDRESS_SIZE; + } } diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 78171d03c..624e72f0c 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -275,6 +275,21 @@ public final class BinaryDictInputOutput { } } + /** + * Compute the binary size of the character array. + * + * If only one character, this is the size of this character. If many, it's the sum of their + * sizes + 1 byte for the terminator. + * + * @param characters the character array + * @return the size of the char array, including the terminator if any + */ + static int getGroupCharactersSize(final int[] characters) { + int size = CharEncoding.getCharArraySize(characters); + if (characters.length > 1) size += FormatSpec.GROUP_TERMINATOR_SIZE; + return size; + } + /** * Compute the binary size of the character array in a group * @@ -285,9 +300,7 @@ public final class BinaryDictInputOutput { * @return the size of the char array, including the terminator if any */ private static int getGroupCharactersSize(final CharGroup group) { - int size = CharEncoding.getCharArraySize(group.mChars); - if (group.hasSeveralChars()) size += FormatSpec.GROUP_TERMINATOR_SIZE; - return size; + return getGroupCharactersSize(group.mChars); } /** @@ -1193,7 +1206,7 @@ public final class BinaryDictInputOutput { // Input methods: Read a binary dictionary to memory. // readDictionaryBinary is the public entry point for them. - private static int getChildrenAddressSize(final int optionFlags, + static int getChildrenAddressSize(final int optionFlags, final FormatOptions formatOptions) { if (formatOptions.mSupportsDynamicUpdate) return FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE; switch (optionFlags & FormatSpec.MASK_GROUP_ADDRESS_TYPE) { diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index ca851c6a9..e88a4aebf 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -188,6 +188,7 @@ public final class FormatSpec { static final int FLAG_IS_BLACKLISTED = 0x01; // These flags are used only in the dynamic dictionary. + static final int MASK_MOVE_AND_DELETE_FLAG = 0xC0; static final int FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE = 0x40; static final int FLAG_IS_MOVED = 0x00 | FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE; static final int FLAG_IS_NOT_MOVED = 0x80 | FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE; -- cgit v1.2.3-83-g751a From c15726482eee1fe9eb5c84e337ae5d40735da2d3 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Thu, 4 Oct 2012 15:49:08 +0900 Subject: Unlink an old file before moving the new file over it This is unlikely to be relevant to this bug, but just in case. Bug: 7274972 Change-Id: I56b31b377af16cc2c15ceb90a19792bed3aab367 --- java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java | 1 + 1 file changed, 1 insertion(+) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index 0b115945b..46b363c10 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -200,6 +200,7 @@ public final class BinaryDictionaryFileDumper { outputStream.flush(); outputStream.close(); final File finalFile = new File(finalFileName); + finalFile.delete(); if (!outputFile.renameTo(finalFile)) { throw new IOException("Can't move the file to its final name"); } -- cgit v1.2.3-83-g751a From 3c6d9fe14840fd2c455ec65b6481ed78f99a5460 Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Mon, 1 Oct 2012 14:50:58 +0900 Subject: Add insertWord. bug: 6669677 Change-Id: Ide55a4931071de9cd42c1cddae63ddd531d2feba --- .../latin/makedict/BinaryDictIOUtils.java | 301 ++++++++++++++++++ .../latin/makedict/BinaryDictInputOutput.java | 3 +- .../latin/makedict/FusionDictionary.java | 2 +- .../latin/makedict/BinaryDictIOUtilsTests.java | 335 +++++++++++++++++++++ 4 files changed, 639 insertions(+), 2 deletions(-) create mode 100644 tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 096ca0992..e5ec449ea 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -27,12 +27,15 @@ import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.Map; import java.util.Stack; public final class BinaryDictIOUtils { private static final boolean DBG = false; + private static final int MSB24 = 0x800000; + private static final int SINT24_MAX = 0x7FFFFF; private static final int MAX_JUMPS = 10000; private BinaryDictIOUtils() { @@ -646,4 +649,302 @@ public final class BinaryDictIOUtils { writeSInt24ToStream(destination, FormatSpec.NO_FORWARD_LINK_ADDRESS); return size + FormatSpec.FORWARD_LINK_ADDRESS_SIZE; } + + /** + * Move a group that is referred to by oldGroupOrigin to the tail of the file. + * And set the children address to the byte after the group. + * + * @param nodeOrigin the address of the tail of the file. + * @param characters + * @param length + * @param flags + * @param frequency + * @param parentAddress + * @param shortcutTargets + * @param bigrams + * @param destination the stream representing the tail of the file. + * @param buffer the buffer representing the (constant-size) body of the file. + * @param oldNodeOrigin + * @param oldGroupOrigin + * @param formatOptions + * @return the size written, in bytes. + * @throws IOException + */ + private static int moveGroup(final int nodeOrigin, final int[] characters, final int length, + final int flags, final int frequency, final int parentAddress, + final ArrayList shortcutTargets, + final ArrayList bigrams, final OutputStream destination, + final FusionDictionaryBufferInterface buffer, final int oldNodeOrigin, + final int oldGroupOrigin, final FormatOptions formatOptions) throws IOException { + int size = 0; + final int newGroupOrigin = nodeOrigin + 1; + final int[] writtenCharacters = Arrays.copyOfRange(characters, 0, length); + final CharGroupInfo tmpInfo = new CharGroupInfo(newGroupOrigin, -1 /* endAddress */, + flags, writtenCharacters, frequency, parentAddress, FormatSpec.NO_CHILDREN_ADDRESS, + shortcutTargets, bigrams); + size = computeGroupSize(tmpInfo, formatOptions); + final CharGroupInfo newInfo = new CharGroupInfo(newGroupOrigin, newGroupOrigin + size, + flags, writtenCharacters, frequency, parentAddress, + nodeOrigin + 1 + size + FormatSpec.FORWARD_LINK_ADDRESS_SIZE, shortcutTargets, + bigrams); + moveCharGroup(destination, buffer, newInfo, oldNodeOrigin, oldGroupOrigin, formatOptions); + return 1 + size + FormatSpec.FORWARD_LINK_ADDRESS_SIZE; + } + + /** + * Insert a word into a binary dictionary. + * + * @param buffer + * @param destination + * @param word + * @param frequency + * @param bigramStrings + * @param shortcuts + * @throws IOException + * @throws UnsupportedFormatException + */ + // TODO: Support batch insertion. + public static void insertWord(final FusionDictionaryBufferInterface buffer, + final OutputStream destination, final String word, final int frequency, + final ArrayList bigramStrings, + final ArrayList shortcuts, final boolean isNotAWord, + final boolean isBlackListEntry) + throws IOException, UnsupportedFormatException { + final ArrayList bigrams = new ArrayList(); + if (bigramStrings != null) { + for (final WeightedString bigram : bigramStrings) { + int position = getTerminalPosition(buffer, bigram.mWord); + if (position == FormatSpec.NOT_VALID_WORD) { + // TODO: figure out what is the correct thing to do here. + } else { + bigrams.add(new PendingAttribute(position, bigram.mFrequency)); + } + } + } + + final boolean isTerminal = true; + final boolean hasBigrams = !bigrams.isEmpty(); + final boolean hasShortcuts = shortcuts != null && !shortcuts.isEmpty(); + + // find the insert position of the word. + if (buffer.position() != 0) buffer.position(0); + final FileHeader header = BinaryDictInputOutput.readHeader(buffer); + + int wordPos = 0, address = buffer.position(), nodeOriginAddress = buffer.position(); + final int[] codePoints = FusionDictionary.getCodePoints(word); + final int wordLen = codePoints.length; + + for (int depth = 0; depth < Constants.Dictionary.MAX_WORD_LENGTH; ++depth) { + if (wordPos >= wordLen) break; + nodeOriginAddress = buffer.position(); + int nodeParentAddress = -1; + final int charGroupCount = BinaryDictInputOutput.readCharGroupCount(buffer); + boolean foundNextGroup = false; + + for (int i = 0; i < charGroupCount; ++i) { + address = buffer.position(); + final CharGroupInfo currentInfo = BinaryDictInputOutput.readCharGroup(buffer, + buffer.position(), header.mFormatOptions); + final boolean isMovedGroup = BinaryDictInputOutput.isMovedGroup(currentInfo.mFlags, + header.mFormatOptions); + if (isMovedGroup) continue; + nodeParentAddress = (currentInfo.mParentAddress == FormatSpec.NO_PARENT_ADDRESS) + ? FormatSpec.NO_PARENT_ADDRESS : currentInfo.mParentAddress + address; + boolean matched = true; + for (int p = 0; p < currentInfo.mCharacters.length; ++p) { + if (wordPos + p >= wordLen) { + /* + * splitting + * before + * abcd - ef + * + * insert "abc" + * + * after + * abc - d - ef + */ + final int newNodeAddress = buffer.limit(); + final int flags = BinaryDictInputOutput.makeCharGroupFlags(p > 1, + isTerminal, 0, hasShortcuts, hasBigrams, false /* isNotAWord */, + false /* isBlackListEntry */, header.mFormatOptions); + int written = moveGroup(newNodeAddress, currentInfo.mCharacters, p, flags, + frequency, nodeParentAddress, shortcuts, bigrams, destination, + buffer, nodeOriginAddress, address, header.mFormatOptions); + + final int[] characters2 = Arrays.copyOfRange(currentInfo.mCharacters, p, + currentInfo.mCharacters.length); + if (currentInfo.mChildrenAddress != FormatSpec.NO_CHILDREN_ADDRESS) { + updateParentAddresses(buffer, currentInfo.mChildrenAddress, + newNodeAddress + written + 1, header.mFormatOptions); + } + final CharGroupInfo newInfo2 = new CharGroupInfo( + newNodeAddress + written + 1, -1 /* endAddress */, + currentInfo.mFlags, characters2, currentInfo.mFrequency, + newNodeAddress + 1, currentInfo.mChildrenAddress, + currentInfo.mShortcutTargets, currentInfo.mBigrams); + writeNode(destination, new CharGroupInfo[] { newInfo2 }); + return; + } else if (codePoints[wordPos + p] != currentInfo.mCharacters[p]) { + if (p > 0) { + /* + * splitting + * before + * ab - cd + * + * insert "ac" + * + * after + * a - b - cd + * | + * - c + */ + + final int newNodeAddress = buffer.limit(); + final int childrenAddress = currentInfo.mChildrenAddress; + + // move prefix + final int prefixFlags = BinaryDictInputOutput.makeCharGroupFlags(p > 1, + false /* isTerminal */, 0 /* childrenAddressSize*/, + false /* hasShortcut */, false /* hasBigrams */, + false /* isNotAWord */, false /* isBlackListEntry */, + header.mFormatOptions); + int written = moveGroup(newNodeAddress, currentInfo.mCharacters, p, + prefixFlags, -1 /* frequency */, nodeParentAddress, null, null, + destination, buffer, nodeOriginAddress, address, + header.mFormatOptions); + + final int[] suffixCharacters = Arrays.copyOfRange( + currentInfo.mCharacters, p, currentInfo.mCharacters.length); + if (currentInfo.mChildrenAddress != FormatSpec.NO_CHILDREN_ADDRESS) { + updateParentAddresses(buffer, currentInfo.mChildrenAddress, + newNodeAddress + written + 1, header.mFormatOptions); + } + final int suffixFlags = BinaryDictInputOutput.makeCharGroupFlags( + suffixCharacters.length > 1, + (currentInfo.mFlags & FormatSpec.FLAG_IS_TERMINAL) != 0, + 0 /* childrenAddressSize */, + (currentInfo.mFlags & FormatSpec.FLAG_HAS_SHORTCUT_TARGETS) + != 0, + (currentInfo.mFlags & FormatSpec.FLAG_HAS_BIGRAMS) != 0, + isNotAWord, isBlackListEntry, header.mFormatOptions); + final CharGroupInfo suffixInfo = new CharGroupInfo( + newNodeAddress + written + 1, -1 /* endAddress */, suffixFlags, + suffixCharacters, currentInfo.mFrequency, newNodeAddress + 1, + currentInfo.mChildrenAddress, currentInfo.mShortcutTargets, + currentInfo.mBigrams); + written += computeGroupSize(suffixInfo, header.mFormatOptions) + 1; + + final int[] newCharacters = Arrays.copyOfRange(codePoints, wordPos + p, + codePoints.length); + final int flags = BinaryDictInputOutput.makeCharGroupFlags( + newCharacters.length > 1, isTerminal, + 0 /* childrenAddressSize */, hasShortcuts, hasBigrams, + isNotAWord, isBlackListEntry, header.mFormatOptions); + final CharGroupInfo newInfo = new CharGroupInfo( + newNodeAddress + written, -1 /* endAddress */, flags, + newCharacters, frequency, newNodeAddress + 1, + FormatSpec.NO_CHILDREN_ADDRESS, shortcuts, bigrams); + writeNode(destination, new CharGroupInfo[] { suffixInfo, newInfo }); + return; + } + matched = false; + break; + } + } + + if (matched) { + if (wordPos + currentInfo.mCharacters.length == wordLen) { + // the word exists in the dictionary. + // only update group. + final int newNodeAddress = buffer.limit(); + final boolean hasMultipleChars = currentInfo.mCharacters.length > 1; + final int flags = BinaryDictInputOutput.makeCharGroupFlags(hasMultipleChars, + isTerminal, 0 /* childrenAddressSize */, hasShortcuts, hasBigrams, + isNotAWord, isBlackListEntry, header.mFormatOptions); + final CharGroupInfo newInfo = new CharGroupInfo(newNodeAddress + 1, + -1 /* endAddress */, flags, currentInfo.mCharacters, frequency, + nodeParentAddress, currentInfo.mChildrenAddress, shortcuts, + bigrams); + moveCharGroup(destination, buffer, newInfo, nodeOriginAddress, address, + header.mFormatOptions); + return; + } + wordPos += currentInfo.mCharacters.length; + if (currentInfo.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS) { + /* + * found the prefix of the word. + * make new node and link to the node from this group. + * + * before + * ab - cd + * + * insert "abcde" + * + * after + * ab - cd - e + */ + final int newNodeAddress = buffer.limit(); + updateChildrenAddress(buffer, address, newNodeAddress, + header.mFormatOptions); + final int newGroupAddress = newNodeAddress + 1; + final boolean hasMultipleChars = (wordLen - wordPos) > 1; + final int flags = BinaryDictInputOutput.makeCharGroupFlags(hasMultipleChars, + isTerminal, 0 /* childrenAddressSize */, hasShortcuts, hasBigrams, + isNotAWord, isBlackListEntry, header.mFormatOptions); + final int[] characters = Arrays.copyOfRange(codePoints, wordPos, wordLen); + final CharGroupInfo newInfo = new CharGroupInfo(newGroupAddress, -1, flags, + characters, frequency, address, FormatSpec.NO_CHILDREN_ADDRESS, + shortcuts, bigrams); + writeNode(destination, new CharGroupInfo[] { newInfo }); + return; + } + buffer.position(currentInfo.mChildrenAddress); + foundNextGroup = true; + break; + } + } + + if (foundNextGroup) continue; + + // reached the end of the array. + final int linkAddressPosition = buffer.position(); + int nextLink = buffer.readUnsignedInt24(); + if ((nextLink & MSB24) != 0) { + nextLink = -(nextLink & SINT24_MAX); + } + if (nextLink == FormatSpec.NO_FORWARD_LINK_ADDRESS) { + /* + * expand this node. + * + * before + * ab - cd + * + * insert "abef" + * + * after + * ab - cd + * | + * - ef + */ + + // change the forward link address. + final int newNodeAddress = buffer.limit(); + buffer.position(linkAddressPosition); + writeSInt24ToBuffer(buffer, newNodeAddress); + + final int[] characters = Arrays.copyOfRange(codePoints, wordPos, wordLen); + final int flags = BinaryDictInputOutput.makeCharGroupFlags(characters.length > 1, + isTerminal, 0 /* childrenAddressSize */, hasShortcuts, hasBigrams, + isNotAWord, isBlackListEntry, header.mFormatOptions); + final CharGroupInfo newInfo = new CharGroupInfo(newNodeAddress + 1, + -1 /* endAddress */, flags, characters, frequency, nodeParentAddress, + FormatSpec.NO_CHILDREN_ADDRESS, shortcuts, bigrams); + writeNode(destination, new CharGroupInfo[]{ newInfo }); + return; + } else { + depth--; + buffer.position(nextLink); + } + } + } } diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 624e72f0c..2d39094ff 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -411,7 +411,8 @@ public final class BinaryDictInputOutput { * Helper method to check whether the group is moved. */ public static boolean isMovedGroup(final int flags, final FormatOptions options) { - return options.mSupportsDynamicUpdate && ((flags & FormatSpec.FLAG_IS_MOVED) == 1); + return options.mSupportsDynamicUpdate + && ((flags & FormatSpec.MASK_GROUP_ADDRESS_TYPE) == FormatSpec.FLAG_IS_MOVED); } /** diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java index 3193ef457..6f1faa192 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java +++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java @@ -279,7 +279,7 @@ public final class FusionDictionary implements Iterable { /** * Helper method to convert a String to an int array. */ - static private int[] getCodePoints(final String word) { + static int[] getCodePoints(final String word) { // TODO: this is a copy-paste of the contents of StringUtils.toCodePointArray, // which is not visible from the makedict package. Factor this code. final char[] characters = word.toCharArray(); diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java new file mode 100644 index 000000000..7607b58eb --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin.makedict; + +import com.android.inputmethod.latin.CollectionUtils; +import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.ByteBufferWrapper; +import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.CharEncoding; +import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.FusionDictionaryBufferInterface; +import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader; +import com.android.inputmethod.latin.makedict.FusionDictionary.Node; +import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; + +import android.test.AndroidTestCase; +import android.test.MoreAsserts; +import android.util.Log; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Random; + +public class BinaryDictIOUtilsTests extends AndroidTestCase{ + private static final String TAG = BinaryDictIOUtilsTests.class.getSimpleName(); + private static final FormatSpec.FormatOptions FORMAT_OPTIONS = + new FormatSpec.FormatOptions(3, true); + private static final int MAX_UNIGRAMS = 1500; + + private static final ArrayList sWords = CollectionUtils.newArrayList(); + + private static final String[] CHARACTERS = { + "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", + "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", + "\u00FC" /* ü */, "\u00E2" /* â */, "\u00F1" /* ñ */, // accented characters + "\u4E9C" /* 亜 */, "\u4F0A" /* 伊 */, "\u5B87" /* 宇 */, // kanji + "\uD841\uDE28" /* 𠘨 */, "\uD840\uDC0B" /* 𠀋 */, "\uD861\uDeD7" /* 𨛗 */ // surrogate pair + }; + + public BinaryDictIOUtilsTests() { + super(); + final Random random = new Random(123456); + sWords.clear(); + for (int i = 0; i < MAX_UNIGRAMS; ++i) { + sWords.add(generateWord(random.nextInt())); + } + } + + // Utilities for test + private String generateWord(final int value) { + final int lengthOfChars = CHARACTERS.length; + StringBuilder builder = new StringBuilder(""); + long lvalue = Math.abs((long)value); + while (lvalue > 0) { + builder.append(CHARACTERS[(int)(lvalue % lengthOfChars)]); + lvalue /= lengthOfChars; + } + if (builder.toString().equals("")) return "a"; + return builder.toString(); + } + + private static void printCharGroup(final CharGroupInfo info) { + Log.d(TAG, " CharGroup at " + info.mOriginalAddress); + Log.d(TAG, " flags = " + info.mFlags); + Log.d(TAG, " parentAddress = " + info.mParentAddress); + Log.d(TAG, " characters = " + new String(info.mCharacters, 0, + info.mCharacters.length)); + if (info.mFrequency != -1) Log.d(TAG, " frequency = " + info.mFrequency); + if (info.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS) { + Log.d(TAG, " children address = no children address"); + } else { + Log.d(TAG, " children address = " + info.mChildrenAddress); + } + if (info.mShortcutTargets != null) { + for (final WeightedString ws : info.mShortcutTargets) { + Log.d(TAG, " shortcuts = " + ws.mWord); + } + } + if (info.mBigrams != null) { + for (final PendingAttribute attr : info.mBigrams) { + Log.d(TAG, " bigram = " + attr.mAddress); + } + } + Log.d(TAG, " end address = " + info.mEndAddress); + } + + private static void printNode(final FusionDictionaryBufferInterface buffer, + final FormatSpec.FormatOptions formatOptions) { + Log.d(TAG, "Node at " + buffer.position()); + final int count = BinaryDictInputOutput.readCharGroupCount(buffer); + Log.d(TAG, " charGroupCount = " + count); + for (int i = 0; i < count; ++i) { + final CharGroupInfo currentInfo = BinaryDictInputOutput.readCharGroup(buffer, + buffer.position(), formatOptions); + printCharGroup(currentInfo); + } + if (formatOptions.mSupportsDynamicUpdate) { + final int forwardLinkAddress = buffer.readUnsignedInt24(); + Log.d(TAG, " forwardLinkAddress = " + forwardLinkAddress); + } + } + + private static void printBinaryFile(final FusionDictionaryBufferInterface buffer) + throws IOException, UnsupportedFormatException { + FileHeader header = BinaryDictInputOutput.readHeader(buffer); + while (buffer.position() < buffer.limit()) { + printNode(buffer, header.mFormatOptions); + } + } + + private int getWordPosition(final File file, final String word) { + int position = FormatSpec.NOT_VALID_WORD; + FileInputStream inStream = null; + try { + inStream = new FileInputStream(file); + final FusionDictionaryBufferInterface buffer = new ByteBufferWrapper( + inStream.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length())); + position = BinaryDictIOUtils.getTerminalPosition(buffer, word); + } catch (IOException e) { + } catch (UnsupportedFormatException e) { + } finally { + if (inStream != null) { + try { + inStream.close(); + } catch (IOException e) { + // do nothing + } + } + } + return position; + } + + // return amount of time to insert a word + private long insertAndCheckWord(final File file, final String word, final int frequency, + final boolean exist) { + RandomAccessFile raFile = null; + FileOutputStream outStream = null; + FusionDictionaryBufferInterface buffer = null; + long amountOfTime = -1; + try { + raFile = new RandomAccessFile(file, "rw"); + buffer = new ByteBufferWrapper(raFile.getChannel().map( + FileChannel.MapMode.READ_WRITE, 0, file.length())); + outStream = new FileOutputStream(file, true); + + if (!exist) { + assertEquals(FormatSpec.NOT_VALID_WORD, getWordPosition(file, word)); + } + final long now = System.nanoTime(); + BinaryDictIOUtils.insertWord(buffer, outStream, word, frequency, null, null, false, + false); + amountOfTime = System.nanoTime() - now; + MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD, getWordPosition(file, word)); + outStream.close(); + raFile.close(); + } catch (IOException e) { + } catch (UnsupportedFormatException e) { + } finally { + if (outStream != null) { + try { + outStream.close(); + } catch (IOException e) { + // do nothing + } + } + if (raFile != null) { + try { + raFile.close(); + } catch (IOException e) { + // do nothing + } + } + } + return amountOfTime; + } + + private void deleteWord(final File file, final String word) { + RandomAccessFile raFile = null; + FusionDictionaryBufferInterface buffer = null; + try { + raFile = new RandomAccessFile(file, "rw"); + buffer = new ByteBufferWrapper(raFile.getChannel().map( + FileChannel.MapMode.READ_WRITE, 0, file.length())); + BinaryDictIOUtils.deleteWord(buffer, word); + } catch (IOException e) { + } catch (UnsupportedFormatException e) { + } finally { + if (raFile != null) { + try { + raFile.close(); + } catch (IOException e) { + // do nothing + } + } + } + } + + + + private void checkReverseLookup(final File file, final String word, final int position) { + FileInputStream inStream = null; + try { + inStream = new FileInputStream(file); + final FusionDictionaryBufferInterface buffer = new ByteBufferWrapper( + inStream.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length())); + final FileHeader header = BinaryDictInputOutput.readHeader(buffer); + assertEquals(word, BinaryDictInputOutput.getWordAtAddress(buffer, header.mHeaderSize, + position - header.mHeaderSize, header.mFormatOptions)); + } catch (IOException e) { + } catch (UnsupportedFormatException e) { + } finally { + if (inStream != null) { + try { + inStream.close(); + } catch (IOException e) { + // do nothing + } + } + } + } + + public void testInsertWord() { + File file = null; + try { + file = File.createTempFile("testInsertWord", ".dict"); + } catch (IOException e) { + fail("IOException while creating temporary file: " + e); + } + + // set an initial dictionary. + final FusionDictionary dict = new FusionDictionary(new Node(), + new FusionDictionary.DictionaryOptions(new HashMap(), false, false)); + dict.add("abcd", 10, null, false); + + try { + final FileOutputStream out = new FileOutputStream(file); + BinaryDictInputOutput.writeDictionaryBinary(out, dict, FORMAT_OPTIONS); + out.close(); + } catch (IOException e) { + fail("IOException while writing an initial dictionary : " + e); + } catch (UnsupportedFormatException e) { + fail("UnsupportedFormatException while writing an initial dictionary : " + e); + } + + MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD, getWordPosition(file, "abcd")); + insertAndCheckWord(file, "abcde", 10, false); + + insertAndCheckWord(file, "abcdefghijklmn", 10, false); + checkReverseLookup(file, "abcdefghijklmn", getWordPosition(file, "abcdefghijklmn")); + + insertAndCheckWord(file, "abcdabcd", 10, false); + checkReverseLookup(file, "abcdabcd", getWordPosition(file, "abcdabcd")); + + // update the existing word. + insertAndCheckWord(file, "abcdabcd", 15, true); + + // split 1 + insertAndCheckWord(file, "ab", 20, false); + + // split 2 + insertAndCheckWord(file, "ami", 30, false); + + deleteWord(file, "ami"); + assertEquals(FormatSpec.NOT_VALID_WORD, getWordPosition(file, "ami")); + + insertAndCheckWord(file, "abcdabfg", 30, false); + + deleteWord(file, "abcd"); + assertEquals(FormatSpec.NOT_VALID_WORD, getWordPosition(file, "abcd")); + } + + public void testRandomWords() { + File file = null; + try { + file = File.createTempFile("testRandomWord", ".dict"); + } catch (IOException e) { + } + assertNotNull(file); + + // set an initial dictionary. + final FusionDictionary dict = new FusionDictionary(new Node(), + new FusionDictionary.DictionaryOptions(new HashMap(), false, + false)); + dict.add("initial", 10, null, false); + + try { + final FileOutputStream out = new FileOutputStream(file); + BinaryDictInputOutput.writeDictionaryBinary(out, dict, FORMAT_OPTIONS); + out.close(); + } catch (IOException e) { + assertTrue(false); + } catch (UnsupportedFormatException e) { + assertTrue(false); + } + + long maxTimeToInsert = 0, sum = 0; + long minTimeToInsert = 100000000; // 1000000000 is an upper bound for minTimeToInsert. + int cnt = 0; + for (final String word : sWords) { + final long diff = insertAndCheckWord(file, word, cnt%255, false); + maxTimeToInsert = Math.max(maxTimeToInsert, diff); + minTimeToInsert = Math.min(minTimeToInsert, diff); + sum += diff; + cnt++; + } + cnt = 0; + for (final String word : sWords) { + MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD, getWordPosition(file, word)); + } + + Log.d(TAG, "max = " + ((double)maxTimeToInsert/1000000) + " ms."); + Log.d(TAG, "min = " + ((double)minTimeToInsert/1000000) + " ms."); + Log.d(TAG, "avg = " + ((double)sum/MAX_UNIGRAMS/1000000) + " ms."); + } +} -- cgit v1.2.3-83-g751a From 2699b45dbc22b56d57690fcc8b4592e0371b8710 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Thu, 4 Oct 2012 15:33:41 +0900 Subject: Always consider a new line the start of a sentence Bug: 7282523 Change-Id: I10a73e99efdfe6acb9a16819694b98c6714fd451 --- java/src/com/android/inputmethod/latin/StringUtils.java | 14 +++++++++----- .../com/android/inputmethod/latin/StringUtilsTests.java | 8 ++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java index 7b65b7343..df7709892 100644 --- a/java/src/com/android/inputmethod/latin/StringUtils.java +++ b/java/src/com/android/inputmethod/latin/StringUtils.java @@ -250,15 +250,19 @@ public final class StringUtils { // Step 3 : Search for the start of a paragraph. From the starting point computed in step 2, // we go back over any space or tab char sitting there. We find the start of a paragraph - // if the first char that's not a space or tab is a start of line (as in, either \n or - // start of text). + // if the first char that's not a space or tab is a start of line (as in \n, start of text, + // or some other similar characters). int j = i; + char prevChar = Keyboard.CODE_SPACE; if (hasSpaceBefore) --j; - while (j > 0 && Character.isWhitespace(cs.charAt(j - 1))) { + while (j > 0) { + prevChar = cs.charAt(j - 1); + if (!Character.isSpaceChar(prevChar) && prevChar != Keyboard.CODE_TAB) break; j--; } - if (j == 0) { - // There is only whitespace between the start of the text and the cursor. Both + if (j <= 0 || Character.isWhitespace(prevChar)) { + // There are only spacing chars between the start of the paragraph and the cursor, + // defined as a isWhitespace() char that is neither a isSpaceChar() nor a tab. Both // MODE_WORDS and MODE_SENTENCES should be active. return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS | TextUtils.CAP_MODE_SENTENCES) & reqModes; diff --git a/tests/src/com/android/inputmethod/latin/StringUtilsTests.java b/tests/src/com/android/inputmethod/latin/StringUtilsTests.java index be3494dc7..3142bd602 100644 --- a/tests/src/com/android/inputmethod/latin/StringUtilsTests.java +++ b/tests/src/com/android/inputmethod/latin/StringUtilsTests.java @@ -140,6 +140,14 @@ public class StringUtilsTests extends AndroidTestCase { allPathsForCaps("Word", c | w, l, true); allPathsForCaps("Word.", c | w | s, l, true); + // Tests after some whitespace + allPathsForCaps("Word\n", c | w | s, l, false); + allPathsForCaps("Word\n", c | w | s, l, true); + allPathsForCaps("Word\n ", c | w | s, l, true); + allPathsForCaps("Word.\n", c | w | s, l, false); + allPathsForCaps("Word.\n", c | w | s, l, true); + allPathsForCaps("Word.\n ", c | w | s, l, true); + l = Locale.FRENCH; allPathsForCaps("\"Word.\" ", c | w, l, false); allPathsForCaps("\"Word\". ", c | w | s, l, false); -- cgit v1.2.3-83-g751a From d2579c4832325bb703e275674706886dce50915d Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Fri, 5 Oct 2012 11:43:21 +0900 Subject: fix writeCharGroup. Change-Id: Ib841afaba0a20c3b300eb7d3e9133243f9f3ae58 --- .../latin/makedict/BinaryDictIOUtils.java | 29 ++++++- .../latin/makedict/BinaryDictIOUtilsTests.java | 98 ++++++++++++++++++---- 2 files changed, 106 insertions(+), 21 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index e5ec449ea..40e089f3a 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -535,10 +535,13 @@ public final class BinaryDictIOUtils { // TODO: Consolidate this code with the code that computes the size of the bigram list // in BinaryDictionaryInputOutput#computeActualNodeSize for (int i = 0; i < info.mBigrams.size(); ++i) { - final int bigramOffset = info.mBigrams.get(i).mAddress - info.mOriginalAddress; + final int bigramFrequency = info.mBigrams.get(i).mFrequency; int bigramFlags = (i < info.mBigrams.size() - 1) ? FormatSpec.FLAG_ATTRIBUTE_HAS_NEXT : 0; + size++; + final int bigramOffset = info.mBigrams.get(i).mAddress - (info.mOriginalAddress + + size); bigramFlags |= (bigramOffset < 0) ? FormatSpec.FLAG_ATTRIBUTE_OFFSET_NEGATIVE : 0; switch (BinaryDictInputOutput.getByteSize(bigramOffset)) { case 1: @@ -553,7 +556,6 @@ public final class BinaryDictIOUtils { } bigramFlags |= bigramFrequency & FormatSpec.FLAG_ATTRIBUTE_FREQUENCY; destination.write((byte)bigramFlags); - size++; size += writeVariableAddress(destination, Math.abs(bigramOffset)); } } @@ -717,7 +719,7 @@ public final class BinaryDictIOUtils { if (position == FormatSpec.NOT_VALID_WORD) { // TODO: figure out what is the correct thing to do here. } else { - bigrams.add(new PendingAttribute(position, bigram.mFrequency)); + bigrams.add(new PendingAttribute(bigram.mFrequency, position)); } } } @@ -947,4 +949,25 @@ public final class BinaryDictIOUtils { } } } + + /** + * Find a word from the buffer. + * + * @param buffer the buffer representing the body of the dictionary file. + * @param word the word searched + * @return the found group + * @throws IOException + * @throws UnsupportedFormatException + */ + public static CharGroupInfo findWordFromBuffer(final FusionDictionaryBufferInterface buffer, + final String word) throws IOException, UnsupportedFormatException { + int position = getTerminalPosition(buffer, word); + if (position != FormatSpec.NOT_VALID_WORD) { + buffer.position(0); + final FileHeader header = BinaryDictInputOutput.readHeader(buffer); + buffer.position(position); + return BinaryDictInputOutput.readCharGroup(buffer, position, header.mFormatOptions); + } + return null; + } } diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java index 7607b58eb..318516845 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java +++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java @@ -28,6 +28,7 @@ import android.test.AndroidTestCase; import android.test.MoreAsserts; import android.util.Log; +import java.io.BufferedOutputStream; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; @@ -41,7 +42,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Random; -public class BinaryDictIOUtilsTests extends AndroidTestCase{ +public class BinaryDictIOUtilsTests extends AndroidTestCase { private static final String TAG = BinaryDictIOUtilsTests.class.getSimpleName(); private static final FormatSpec.FormatOptions FORMAT_OPTIONS = new FormatSpec.FormatOptions(3, true); @@ -150,26 +151,50 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase{ return position; } + private CharGroupInfo findWordFromFile(final File file, final String word) { + FileInputStream inStream = null; + CharGroupInfo info = null; + try { + inStream = new FileInputStream(file); + final FusionDictionaryBufferInterface buffer = new ByteBufferWrapper( + inStream.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length())); + info = BinaryDictIOUtils.findWordFromBuffer(buffer, word); + } catch (IOException e) { + } catch (UnsupportedFormatException e) { + } finally { + if (inStream != null) { + try { + inStream.close(); + } catch (IOException e) { + // do nothing + } + } + } + return info; + } + // return amount of time to insert a word private long insertAndCheckWord(final File file, final String word, final int frequency, - final boolean exist) { + final boolean exist, final ArrayList bigrams, + final ArrayList shortcuts) { RandomAccessFile raFile = null; - FileOutputStream outStream = null; + BufferedOutputStream outStream = null; FusionDictionaryBufferInterface buffer = null; long amountOfTime = -1; try { raFile = new RandomAccessFile(file, "rw"); buffer = new ByteBufferWrapper(raFile.getChannel().map( FileChannel.MapMode.READ_WRITE, 0, file.length())); - outStream = new FileOutputStream(file, true); + outStream = new BufferedOutputStream(new FileOutputStream(file, true)); if (!exist) { assertEquals(FormatSpec.NOT_VALID_WORD, getWordPosition(file, word)); } final long now = System.nanoTime(); - BinaryDictIOUtils.insertWord(buffer, outStream, word, frequency, null, null, false, - false); + BinaryDictIOUtils.insertWord(buffer, outStream, word, frequency, bigrams, shortcuts, + false, false); amountOfTime = System.nanoTime() - now; + outStream.flush(); MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD, getWordPosition(file, word)); outStream.close(); raFile.close(); @@ -215,8 +240,6 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase{ } } - - private void checkReverseLookup(final File file, final String word, final int position) { FileInputStream inStream = null; try { @@ -242,7 +265,7 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase{ public void testInsertWord() { File file = null; try { - file = File.createTempFile("testInsertWord", ".dict"); + file = File.createTempFile("testInsertWord", ".dict", getContext().getCacheDir()); } catch (IOException e) { fail("IOException while creating temporary file: " + e); } @@ -263,36 +286,74 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase{ } MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD, getWordPosition(file, "abcd")); - insertAndCheckWord(file, "abcde", 10, false); + insertAndCheckWord(file, "abcde", 10, false, null, null); - insertAndCheckWord(file, "abcdefghijklmn", 10, false); + insertAndCheckWord(file, "abcdefghijklmn", 10, false, null, null); checkReverseLookup(file, "abcdefghijklmn", getWordPosition(file, "abcdefghijklmn")); - insertAndCheckWord(file, "abcdabcd", 10, false); + insertAndCheckWord(file, "abcdabcd", 10, false, null, null); checkReverseLookup(file, "abcdabcd", getWordPosition(file, "abcdabcd")); // update the existing word. - insertAndCheckWord(file, "abcdabcd", 15, true); + insertAndCheckWord(file, "abcdabcd", 15, true, null, null); // split 1 - insertAndCheckWord(file, "ab", 20, false); + insertAndCheckWord(file, "ab", 20, false, null, null); // split 2 - insertAndCheckWord(file, "ami", 30, false); + insertAndCheckWord(file, "ami", 30, false, null, null); deleteWord(file, "ami"); assertEquals(FormatSpec.NOT_VALID_WORD, getWordPosition(file, "ami")); - insertAndCheckWord(file, "abcdabfg", 30, false); + insertAndCheckWord(file, "abcdabfg", 30, false, null, null); deleteWord(file, "abcd"); assertEquals(FormatSpec.NOT_VALID_WORD, getWordPosition(file, "abcd")); } + public void testInsertWordWithBigrams() { + File file = null; + try { + file = File.createTempFile("testInsertWordWithBigrams", ".dict", + getContext().getCacheDir()); + } catch (IOException e) { + fail("IOException while creating temporary file: " + e); + } + + // set an initial dictionary. + final FusionDictionary dict = new FusionDictionary(new Node(), + new FusionDictionary.DictionaryOptions(new HashMap(), false, false)); + dict.add("abcd", 10, null, false); + dict.add("efgh", 15, null, false); + + try { + final FileOutputStream out = new FileOutputStream(file); + BinaryDictInputOutput.writeDictionaryBinary(out, dict, FORMAT_OPTIONS); + out.close(); + } catch (IOException e) { + fail("IOException while writing an initial dictionary : " + e); + } catch (UnsupportedFormatException e) { + fail("UnsupportedFormatException while writing an initial dictionary : " + e); + } + + final ArrayList banana = new ArrayList(); + banana.add(new WeightedString("banana", 10)); + + insertAndCheckWord(file, "banana", 0, false, null, null); + insertAndCheckWord(file, "recursive", 60, true, banana, null); + + final CharGroupInfo info = findWordFromFile(file, "recursive"); + int bananaPos = getWordPosition(file, "banana"); + assertNotNull(info.mBigrams); + assertEquals(info.mBigrams.size(), 1); + assertEquals(info.mBigrams.get(0).mAddress, bananaPos); + } + public void testRandomWords() { File file = null; try { - file = File.createTempFile("testRandomWord", ".dict"); + file = File.createTempFile("testRandomWord", ".dict", getContext().getCacheDir()); } catch (IOException e) { } assertNotNull(file); @@ -317,7 +378,8 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase{ long minTimeToInsert = 100000000; // 1000000000 is an upper bound for minTimeToInsert. int cnt = 0; for (final String word : sWords) { - final long diff = insertAndCheckWord(file, word, cnt%255, false); + final long diff = insertAndCheckWord(file, word, + cnt % FormatSpec.MAX_TERMINAL_FREQUENCY, false, null, null); maxTimeToInsert = Math.max(maxTimeToInsert, diff); minTimeToInsert = Math.min(minTimeToInsert, diff); sum += diff; -- cgit v1.2.3-83-g751a From 792980d4aa4d0d91a5acfcbaba3f4471f1d2c073 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 5 Oct 2012 18:29:06 +0900 Subject: Avoid calling switchToLastInputMethod when other IMEs are in effect (DO NOT MERGE) Bug: 7299050 Change-Id: Ife6721a5fcbc4872bd36ffd8a8b81b04d73aebec --- java/src/com/android/inputmethod/latin/LatinIME.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index fe6ad4901..d98966e96 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1219,22 +1219,25 @@ public final class LatinIME extends InputMethodService implements KeyboardAction mConnection.performEditorAction(actionId); } + // TODO: Revise the language switch key behavior to make it much smarter and more reasonable. private void handleLanguageSwitchKey() { - final boolean includesOtherImes = mCurrentSettings.mIncludesOtherImesInLanguageSwitchList; final IBinder token = getWindow().getWindow().getAttributes().token; + if (mCurrentSettings.mIncludesOtherImesInLanguageSwitchList) { + mImm.switchToNextInputMethod(token, false /* onlyCurrentIme */); + return; + } if (mShouldSwitchToLastSubtype) { final InputMethodSubtype lastSubtype = mImm.getLastInputMethodSubtype(); final boolean lastSubtypeBelongsToThisIme = ImfUtils.checkIfSubtypeBelongsToThisImeAndEnabled(this, lastSubtype); - if ((includesOtherImes || lastSubtypeBelongsToThisIme) - && mImm.switchToLastInputMethod(token)) { + if (lastSubtypeBelongsToThisIme && mImm.switchToLastInputMethod(token)) { mShouldSwitchToLastSubtype = false; } else { - mImm.switchToNextInputMethod(token, !includesOtherImes); + mImm.switchToNextInputMethod(token, true /* onlyCurrentIme */); mShouldSwitchToLastSubtype = true; } } else { - mImm.switchToNextInputMethod(token, !includesOtherImes); + mImm.switchToNextInputMethod(token, true /* onlyCurrentIme */); } } -- cgit v1.2.3-83-g751a From fc62882591e9a6f25105b9d67db62469b0043348 Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Sun, 7 Oct 2012 12:05:23 +0900 Subject: Fix a small typo Change-Id: I813d97b9453f8aa7aae99bd165336b1e5a81dc6a --- java/src/com/android/inputmethod/latin/LatinIME.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index c0938cf97..5a6a50238 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1230,7 +1230,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction final InputMethodSubtype lastSubtype = mImm.getLastInputMethodSubtype(); final boolean lastSubtypeBelongsToThisIme = ImfUtils.checkIfSubtypeBelongsToThisImeAndEnabled(this, lastSubtype); - if (lastSubtypeBelongsToThisIme && mImm.switchToLastInputMethod(token)) { + if (lastSubtypeBelongsToThisIme && mImm.switchToLastInputMethod(token)) { mShouldSwitchToLastSubtype = false; } else { mImm.switchToNextInputMethod(token, true /* onlyCurrentIme */); -- cgit v1.2.3-83-g751a From b02ee3d67a1884b6ff59cc16c29a476845c0694f Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Mon, 8 Oct 2012 11:46:14 +0900 Subject: Make use of the NELEMS and KEYCODE_SPACE macro. Also, remove an unused parameter. Change-Id: I3c7e6c59990c92b0d5e2fb80493e8673cdd37b09 --- .../inputmethod/latin/BinaryDictionary.java | 12 ++++------- ..._android_inputmethod_keyboard_ProximityInfo.cpp | 6 +++--- ..._android_inputmethod_latin_BinaryDictionary.cpp | 12 +++++------ ...ndroid_inputmethod_latin_DicTraverseSession.cpp | 4 ++-- native/jni/src/char_utils.cpp | 7 +++---- native/jni/src/correction.cpp | 2 +- native/jni/src/correction.h | 1 - native/jni/src/defines.h | 6 ++++-- native/jni/src/dictionary.cpp | 7 +++---- native/jni/src/dictionary.h | 4 ++-- native/jni/src/proximity_info_state.cpp | 2 +- native/jni/src/unigram_dictionary.cpp | 24 ++++++++-------------- native/jni/src/unigram_dictionary.h | 5 ++--- 13 files changed, 39 insertions(+), 53 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 7184f1d8a..9c48aa1a4 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -31,7 +31,7 @@ import java.util.Locale; * Implements a static, compacted, binary dictionary of standard words. */ public final class BinaryDictionary extends Dictionary { - + private static final String TAG = BinaryDictionary.class.getSimpleName(); public static final String DICTIONARY_PACK_AUTHORITY = "com.android.inputmethod.latin.dictionarypack"; @@ -45,12 +45,9 @@ public final class BinaryDictionary extends Dictionary { public static final int MAX_WORDS = 18; public static final int MAX_SPACES = 16; - private static final String TAG = BinaryDictionary.class.getSimpleName(); private static final int MAX_PREDICTIONS = 60; private static final int MAX_RESULTS = Math.max(MAX_PREDICTIONS, MAX_WORDS); - private static final int TYPED_LETTER_MULTIPLIER = 2; - private long mNativeDict; private final Locale mLocale; private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH]; @@ -106,8 +103,7 @@ public final class BinaryDictionary extends Dictionary { } private native long openNative(String sourceDir, long dictOffset, long dictSize, - int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, int maxWords, - int maxPredictions); + int fullWordMultiplier, int maxWordLength, int maxWords, int maxPredictions); private native void closeNative(long dict); private native int getFrequencyNative(long dict, int[] word); private native boolean isValidBigramNative(long dict, int[] word1, int[] word2); @@ -121,8 +117,8 @@ public final class BinaryDictionary extends Dictionary { // TODO: Move native dict into session private final void loadDictionary(String path, long startOffset, long length) { - mNativeDict = openNative(path, startOffset, length, TYPED_LETTER_MULTIPLIER, - FULL_WORD_SCORE_MULTIPLIER, MAX_WORD_LENGTH, MAX_WORDS, MAX_PREDICTIONS); + mNativeDict = openNative(path, startOffset, length, FULL_WORD_SCORE_MULTIPLIER, + MAX_WORD_LENGTH, MAX_WORDS, MAX_PREDICTIONS); } @Override diff --git a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp index 560b3a533..2423bb53b 100644 --- a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp +++ b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "LatinIME: jni: ProximityInfo" #include "com_android_inputmethod_keyboard_ProximityInfo.h" +#include "defines.h" #include "jni.h" #include "jni_common.h" #include "proximity_info.h" @@ -41,7 +42,7 @@ static void latinime_Keyboard_release(JNIEnv *env, jobject object, jlong proximi delete pi; } -static JNINativeMethod sKeyboardMethods[] = { +static JNINativeMethod sMethods[] = { {"setProximityInfoNative", "(Ljava/lang/String;IIIIII[II[I[I[I[I[I[F[F[F)J", reinterpret_cast(latinime_Keyboard_setProximityInfo)}, {"releaseProximityInfoNative", "(J)V", reinterpret_cast(latinime_Keyboard_release)} @@ -49,7 +50,6 @@ static JNINativeMethod sKeyboardMethods[] = { int register_ProximityInfo(JNIEnv *env) { const char *const kClassPathName = "com/android/inputmethod/keyboard/ProximityInfo"; - return registerNativeMethods(env, kClassPathName, sKeyboardMethods, - sizeof(sKeyboardMethods) / sizeof(sKeyboardMethods[0])); + return registerNativeMethods(env, kClassPathName, sMethods, NELEMS(sMethods)); } } // namespace latinime diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp index dd2513f9f..42f7da9d3 100644 --- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp +++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp @@ -44,9 +44,8 @@ class ProximityInfo; static void releaseDictBuf(const void *dictBuf, const size_t length, const int fd); static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object, - jstring sourceDir, jlong dictOffset, jlong dictSize, - jint typedLetterMultiplier, jint fullWordMultiplier, jint maxWordLength, jint maxWords, - jint maxPredictions) { + jstring sourceDir, jlong dictOffset, jlong dictSize, jint fullWordMultiplier, + jint maxWordLength, jint maxWords, jint maxPredictions) { PROF_OPEN; PROF_START(66); const jsize sourceDirUtf8Length = env->GetStringUTFLength(sourceDir); @@ -121,7 +120,7 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object, #endif // USE_MMAP_FOR_DICTIONARY } else { dictionary = new Dictionary(dictBuf, static_cast(dictSize), fd, adjust, - typedLetterMultiplier, fullWordMultiplier, maxWordLength, maxWords, maxPredictions); + fullWordMultiplier, maxWordLength, maxWords, maxPredictions); } PROF_END(66); PROF_CLOSE; @@ -277,7 +276,7 @@ static void releaseDictBuf(const void *dictBuf, const size_t length, const int f } static JNINativeMethod sMethods[] = { - {"openNative", "(Ljava/lang/String;JJIIIII)J", + {"openNative", "(Ljava/lang/String;JJIIII)J", reinterpret_cast(latinime_BinaryDictionary_open)}, {"closeNative", "(J)V", reinterpret_cast(latinime_BinaryDictionary_close)}, {"getSuggestionsNative", "(JJJ[I[I[I[I[IIIZ[IZ[C[I[I[I)I", @@ -294,7 +293,6 @@ static JNINativeMethod sMethods[] = { int register_BinaryDictionary(JNIEnv *env) { const char *const kClassPathName = "com/android/inputmethod/latin/BinaryDictionary"; - return registerNativeMethods(env, kClassPathName, sMethods, - sizeof(sMethods) / sizeof(sMethods[0])); + return registerNativeMethods(env, kClassPathName, sMethods, NELEMS(sMethods)); } } // namespace latinime diff --git a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp index 5d405f117..7bb8dc56e 100644 --- a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp +++ b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "LatinIME: jni: Session" #include "com_android_inputmethod_latin_DicTraverseSession.h" +#include "defines.h" #include "dic_traverse_wrapper.h" #include "jni.h" #include "jni_common.h" @@ -57,7 +58,6 @@ static JNINativeMethod sMethods[] = { int register_DicTraverseSession(JNIEnv *env) { const char *const kClassPathName = "com/android/inputmethod/latin/DicTraverseSession"; - return registerNativeMethods(env, kClassPathName, sMethods, - sizeof(sMethods) / sizeof(sMethods[0])); + return registerNativeMethods(env, kClassPathName, sMethods, NELEMS(sMethods)); } } // namespace latinime diff --git a/native/jni/src/char_utils.cpp b/native/jni/src/char_utils.cpp index d0547a982..9d27cadad 100644 --- a/native/jni/src/char_utils.cpp +++ b/native/jni/src/char_utils.cpp @@ -17,6 +17,7 @@ #include #include "char_utils.h" +#include "defines.h" namespace latinime { @@ -33,7 +34,7 @@ struct LatinCapitalSmallPair { // // unsigned short c, cc, ccc, ccc2; // for (c = 0; c < 0xFFFF ; c++) { -// if (c < sizeof(BASE_CHARS) / sizeof(BASE_CHARS[0])) { +// if (c < NELEMS(BASE_CHARS)) { // cc = BASE_CHARS[c]; // } else { // cc = c; @@ -894,9 +895,7 @@ static int compare_pair_capital(const void *a, const void *b) { unsigned short latin_tolower(const unsigned short c) { struct LatinCapitalSmallPair *p = static_cast(bsearch(&c, SORTED_CHAR_MAP, - sizeof(SORTED_CHAR_MAP) / sizeof(SORTED_CHAR_MAP[0]), - sizeof(SORTED_CHAR_MAP[0]), - compare_pair_capital)); + NELEMS(SORTED_CHAR_MAP), sizeof(SORTED_CHAR_MAP[0]), compare_pair_capital)); return p ? p->small : c; } } // namespace latinime diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp index 524abe9a1..d57b0e370 100644 --- a/native/jni/src/correction.cpp +++ b/native/jni/src/correction.cpp @@ -1118,7 +1118,7 @@ float Correction::RankingAlgorithm::calcNormalizedScore(const unsigned short *be const int distance = editDistance(before, beforeLength, after, afterLength); int spaceCount = 0; for (int i = 0; i < afterLength; ++i) { - if (after[i] == CODE_SPACE) { + if (after[i] == KEYCODE_SPACE) { ++spaceCount; } } diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h index f016d5453..a099853e6 100644 --- a/native/jni/src/correction.h +++ b/native/jni/src/correction.h @@ -116,7 +116,6 @@ class Correction { static int editDistance(const unsigned short *before, const int beforeLength, const unsigned short *after, const int afterLength); private: - static const int CODE_SPACE = ' '; static const int MAX_INITIAL_SCORE = 255; }; diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h index ea0f0ef70..1bb031312 100644 --- a/native/jni/src/defines.h +++ b/native/jni/src/defines.h @@ -344,8 +344,8 @@ static inline void prof_out(void) { #define MULTIPLE_WORDS_DEMOTION_RATE 80 #define MIN_INPUT_LENGTH_FOR_THREE_OR_MORE_WORDS_CORRECTION 6 -#define TWO_WORDS_CORRECTION_WITH_OTHER_ERROR_THRESHOLD 0.35 -#define START_TWO_WORDS_CORRECTION_THRESHOLD 0.185 +#define TWO_WORDS_CORRECTION_WITH_OTHER_ERROR_THRESHOLD 0.35f +#define START_TWO_WORDS_CORRECTION_THRESHOLD 0.185f /* heuristic... This should be changed if we change the unit of the frequency. */ #define SUPPRESS_SHORT_MULTIPLE_WORDS_THRESHOLD_FREQ (MAX_FREQ * 58 / 100) @@ -392,6 +392,8 @@ static inline void prof_out(void) { template inline T min(T a, T b) { return a < b ? a : b; } template inline T max(T a, T b) { return a > b ? a : b; } +#define NELEMS(x) (sizeof(x) / sizeof((x)[0])) + // The ratio of neutral area radius to sweet spot radius. #define NEUTRAL_AREA_RADIUS_RATIO 1.3f diff --git a/native/jni/src/dictionary.cpp b/native/jni/src/dictionary.cpp index 2fbe83e86..81789ccfc 100644 --- a/native/jni/src/dictionary.cpp +++ b/native/jni/src/dictionary.cpp @@ -30,13 +30,12 @@ namespace latinime { // TODO: Change the type of all keyCodes to uint32_t Dictionary::Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, - int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, int maxWords, - int maxPredictions) + int fullWordMultiplier, int maxWordLength, int maxWords, int maxPredictions) : mDict(static_cast(dict)), mOffsetDict((static_cast(dict)) + BinaryFormat::getHeaderSize(mDict)), mDictSize(dictSize), mMmapFd(mmapFd), mDictBufAdjust(dictBufAdjust), - mUnigramDictionary(new UnigramDictionary(mOffsetDict, typedLetterMultiplier, - fullWordMultiplier, maxWordLength, maxWords, BinaryFormat::getFlags(mDict))), + mUnigramDictionary(new UnigramDictionary(mOffsetDict, fullWordMultiplier, maxWordLength, + maxWords, BinaryFormat::getFlags(mDict))), mBigramDictionary(new BigramDictionary(mOffsetDict, maxWordLength, maxPredictions)), mGestureDecoder(new GestureDecoderWrapper(maxWordLength, maxWords)) { if (DEBUG_DICT) { diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h index a1358890d..120ca5f7f 100644 --- a/native/jni/src/dictionary.h +++ b/native/jni/src/dictionary.h @@ -41,8 +41,8 @@ class Dictionary { const static int KIND_SHORTCUT = 7; // A shortcut const static int KIND_PREDICTION = 8; // A prediction (== a suggestion with no input) - Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, int typedLetterMultipler, - int fullWordMultiplier, int maxWordLength, int maxWords, int maxPredictions); + Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, int fullWordMultiplier, + int maxWordLength, int maxWords, int maxPredictions); int getSuggestions(ProximityInfo *proximityInfo, void *traverseSession, int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *codes, int codesSize, diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp index 392ec8194..015174356 100644 --- a/native/jni/src/proximity_info_state.cpp +++ b/native/jni/src/proximity_info_state.cpp @@ -518,7 +518,7 @@ float ProximityInfoState::getPointToKeyLength(const int inputIndex, const int co } int ProximityInfoState::getSpaceY() const { - const int keyId = mProximityInfo->getKeyIndexOf(' '); + const int keyId = mProximityInfo->getKeyIndexOf(KEYCODE_SPACE); return mProximityInfo->getKeyCenterYOfKeyIdG(keyId); } diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp index 49d044fbc..3b485a055 100644 --- a/native/jni/src/unigram_dictionary.cpp +++ b/native/jni/src/unigram_dictionary.cpp @@ -41,14 +41,12 @@ const UnigramDictionary::digraph_t UnigramDictionary::FRENCH_LIGATURES_DIGRAPHS[ { 'o', 'e', 0x0153 } }; // U+0153 : LATIN SMALL LIGATURE OE // TODO: check the header -UnigramDictionary::UnigramDictionary(const uint8_t *const streamStart, int typedLetterMultiplier, - int fullWordMultiplier, int maxWordLength, int maxWords, const unsigned int flags) - : DICT_ROOT(streamStart), MAX_WORD_LENGTH(maxWordLength), MAX_WORDS(maxWords), - TYPED_LETTER_MULTIPLIER(typedLetterMultiplier), FULL_WORD_MULTIPLIER(fullWordMultiplier), - // TODO : remove this variable. - ROOT_POS(0), - BYTES_IN_ONE_CHAR(sizeof(int)), - MAX_DIGRAPH_SEARCH_DEPTH(DEFAULT_MAX_DIGRAPH_SEARCH_DEPTH), FLAGS(flags) { +UnigramDictionary::UnigramDictionary(const uint8_t *const streamStart, int fullWordMultiplier, + int maxWordLength, int maxWords, const unsigned int flags) + : DICT_ROOT(streamStart), MAX_WORD_LENGTH(maxWordLength), MAX_WORDS(maxWords), + FULL_WORD_MULTIPLIER(fullWordMultiplier), // TODO : remove this variable. + ROOT_POS(0), BYTES_IN_ONE_CHAR(sizeof(int)), + MAX_DIGRAPH_SEARCH_DEPTH(DEFAULT_MAX_DIGRAPH_SEARCH_DEPTH), FLAGS(flags) { if (DEBUG_DICT) { AKLOGI("UnigramDictionary - constructor"); } @@ -188,8 +186,7 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *x getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, codesBuffer, xCoordinatesBuffer, yCoordinatesBuffer, codesSize, bigramMap, bigramFilter, useFullEditDistance, codes, codesSize, 0, codesBuffer, &masterCorrection, - &queuePool, GERMAN_UMLAUT_DIGRAPHS, - sizeof(GERMAN_UMLAUT_DIGRAPHS) / sizeof(GERMAN_UMLAUT_DIGRAPHS[0])); + &queuePool, GERMAN_UMLAUT_DIGRAPHS, NELEMS(GERMAN_UMLAUT_DIGRAPHS)); } else if (BinaryFormat::REQUIRES_FRENCH_LIGATURES_PROCESSING & FLAGS) { int codesBuffer[getCodesBufferSize(codes, codesSize)]; int xCoordinatesBuffer[codesSize]; @@ -197,8 +194,7 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *x getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, codesBuffer, xCoordinatesBuffer, yCoordinatesBuffer, codesSize, bigramMap, bigramFilter, useFullEditDistance, codes, codesSize, 0, codesBuffer, &masterCorrection, - &queuePool, FRENCH_LIGATURES_DIGRAPHS, - sizeof(FRENCH_LIGATURES_DIGRAPHS) / sizeof(FRENCH_LIGATURES_DIGRAPHS[0])); + &queuePool, FRENCH_LIGATURES_DIGRAPHS, NELEMS(FRENCH_LIGATURES_DIGRAPHS)); } else { // Normal processing getWordSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, codesSize, bigramMap, bigramFilter, useFullEditDistance, &masterCorrection, &queuePool); @@ -314,8 +310,6 @@ void UnigramDictionary::initSuggestions(ProximityInfo *proximityInfo, const int correction->initCorrection(proximityInfo, inputSize, maxDepth); } -static const char SPACE = ' '; - void UnigramDictionary::getOneWordSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, const int *ycoordinates, const int *codes, const std::map *bigramMap, const uint8_t *bigramFilter, @@ -570,7 +564,7 @@ int UnigramDictionary::getSubStringSuggestion( if (outputWordStartPos + nextWordLength >= MAX_WORD_LENGTH) { return FLAG_MULTIPLE_SUGGEST_SKIP; } - outputWord[tempOutputWordLength] = SPACE; + outputWord[tempOutputWordLength] = KEYCODE_SPACE; if (outputWordLength) { ++*outputWordLength; } diff --git a/native/jni/src/unigram_dictionary.h b/native/jni/src/unigram_dictionary.h index 57129bb07..244d78d8c 100644 --- a/native/jni/src/unigram_dictionary.h +++ b/native/jni/src/unigram_dictionary.h @@ -39,8 +39,8 @@ class UnigramDictionary { static const int FLAG_MULTIPLE_SUGGEST_ABORT = 0; static const int FLAG_MULTIPLE_SUGGEST_SKIP = 1; static const int FLAG_MULTIPLE_SUGGEST_CONTINUE = 2; - UnigramDictionary(const uint8_t *const streamStart, int typedLetterMultipler, - int fullWordMultiplier, int maxWordLength, int maxWords, const unsigned int flags); + UnigramDictionary(const uint8_t *const streamStart, int fullWordMultiplier, int maxWordLength, + int maxWords, const unsigned int flags); int getFrequency(const int32_t *const inWord, const int length) const; int getBigramPosition(int pos, unsigned short *word, int offset, int length) const; int getSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, @@ -115,7 +115,6 @@ class UnigramDictionary { const uint8_t *const DICT_ROOT; const int MAX_WORD_LENGTH; const int MAX_WORDS; - const int TYPED_LETTER_MULTIPLIER; const int FULL_WORD_MULTIPLIER; const int ROOT_POS; const unsigned int BYTES_IN_ONE_CHAR; -- cgit v1.2.3-83-g751a From 99b84b42f9517cbf7856aec93a6d5de30daaa325 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Tue, 9 Oct 2012 19:15:06 +0900 Subject: Use a freq of 1 instead of 0 for non-word shortcuts. Also fix a spelling mistake in a comment Bug: 7301525 Change-Id: I4437403dce620fed03871485ee04f13c51ce34fc --- java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java | 2 +- .../src/android/inputmethod/latin/dicttool/XmlDictInputOutput.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index fa9f79ecd..201a10187 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -350,7 +350,7 @@ final class BinaryDictionaryGetter { // of the dictionary would lose whitelist functionality. private static boolean hackCanUseDictionaryFile(final Locale locale, final File f) { // Only for English - other languages didn't have a whitelist, hence this - // ad-hock ## HACK ## + // ad-hoc ## HACK ## if (!Locale.ENGLISH.getLanguage().equals(locale.getLanguage())) return true; FileInputStream inStream = null; diff --git a/tools/dicttool/src/android/inputmethod/latin/dicttool/XmlDictInputOutput.java b/tools/dicttool/src/android/inputmethod/latin/dicttool/XmlDictInputOutput.java index c31cd724a..252c3d655 100644 --- a/tools/dicttool/src/android/inputmethod/latin/dicttool/XmlDictInputOutput.java +++ b/tools/dicttool/src/android/inputmethod/latin/dicttool/XmlDictInputOutput.java @@ -93,7 +93,7 @@ public class XmlDictInputOutput { final FusionDictionary dict = mDictionary; for (final String shortcutOnly : mShortcutsMap.keySet()) { if (dict.hasWord(shortcutOnly)) continue; - dict.add(shortcutOnly, 0, mShortcutsMap.get(shortcutOnly), true /* isNotAWord */); + dict.add(shortcutOnly, 1, mShortcutsMap.get(shortcutOnly), true /* isNotAWord */); } mDictionary = null; mShortcutsMap.clear(); -- cgit v1.2.3-83-g751a From 66c90cd2ae49c49da8aeda5ab1d86bd9b76434c7 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Thu, 11 Oct 2012 16:08:25 +0900 Subject: Put temporary files under a separate directory. Bug: 7328003 Change-Id: Ibe5278ea209d149f87fd08785c77b17e3859948e --- .../inputmethod/latin/BinaryDictionaryFileDumper.java | 5 +++-- .../android/inputmethod/latin/BinaryDictionaryGetter.java | 12 ++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index 46b363c10..b0b65edb6 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -46,7 +46,7 @@ public final class BinaryDictionaryFileDumper { /** * The size of the temporary buffer to copy files. */ - private static final int FILE_READ_BUFFER_SIZE = 1024; + private static final int FILE_READ_BUFFER_SIZE = 8192; // TODO: make the following data common with the native code private static final byte[] MAGIC_NUMBER_VERSION_1 = new byte[] { (byte)0x78, (byte)0xB1, (byte)0x00, (byte)0x00 }; @@ -149,7 +149,7 @@ public final class BinaryDictionaryFileDumper { final Uri.Builder wordListUriBuilder = getProviderUriBuilder(id); final String finalFileName = BinaryDictionaryGetter.getCacheFileName(id, locale, context); - final String tempFileName = finalFileName + ".tmp"; + final String tempFileName = BinaryDictionaryGetter.getTempFileName(id, context); for (int mode = MODE_MIN; mode <= MODE_MAX; ++mode) { InputStream originalSourceStream = null; @@ -287,6 +287,7 @@ public final class BinaryDictionaryFileDumper { * @param input the stream to be copied. * @param output an output stream to copy the data to. */ + // TODO: make output a BufferedOutputStream private static void checkMagicAndCopyFileTo(final BufferedInputStream input, final FileOutputStream output) throws FileNotFoundException, IOException { // Check the magic number diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index 201a10187..c747dc673 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -163,6 +163,18 @@ final class BinaryDictionaryGetter { return getCacheDirectoryForLocale(locale, context) + File.separator + fileName; } + /** + * Generates a unique temporary file name in the app cache directory. + * + * This is unique as long as it doesn't get called twice in the same millisecond by the same + * thread, which should be more than enough for our purposes. + */ + public static String getTempFileName(String id, Context context) { + final String fileName = replaceFileNameDangerousCharacters(id); + return context.getCacheDir() + File.separator + fileName + "." + + Thread.currentThread().getId() + "." + System.currentTimeMillis(); + } + /** * Returns a file address from a resource, or null if it cannot be opened. */ -- cgit v1.2.3-83-g751a From 01e0913ad20b24cc2b7b4dc2f4cbac03ccd4bc0e Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Fri, 12 Oct 2012 18:07:30 +0900 Subject: Make a better choice for the temporary file Change-Id: I745bb285b6b52875c8d2b3a94deb962352f9754e --- .../android/inputmethod/latin/BinaryDictionaryFileDumper.java | 8 +++++++- .../com/android/inputmethod/latin/BinaryDictionaryGetter.java | 9 ++------- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index b0b65edb6..bed31a7d1 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -149,7 +149,13 @@ public final class BinaryDictionaryFileDumper { final Uri.Builder wordListUriBuilder = getProviderUriBuilder(id); final String finalFileName = BinaryDictionaryGetter.getCacheFileName(id, locale, context); - final String tempFileName = BinaryDictionaryGetter.getTempFileName(id, context); + String tempFileName; + try { + tempFileName = BinaryDictionaryGetter.getTempFileName(id, context); + } catch (IOException e) { + Log.e(TAG, "Can't open the temporary file", e); + return null; + } for (int mode = MODE_MIN; mode <= MODE_MAX; ++mode) { InputStream originalSourceStream = null; diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index c747dc673..ecb61b46f 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -165,14 +165,9 @@ final class BinaryDictionaryGetter { /** * Generates a unique temporary file name in the app cache directory. - * - * This is unique as long as it doesn't get called twice in the same millisecond by the same - * thread, which should be more than enough for our purposes. */ - public static String getTempFileName(String id, Context context) { - final String fileName = replaceFileNameDangerousCharacters(id); - return context.getCacheDir() + File.separator + fileName + "." - + Thread.currentThread().getId() + "." + System.currentTimeMillis(); + public static String getTempFileName(String id, Context context) throws IOException { + return File.createTempFile(replaceFileNameDangerousCharacters(id), null).getAbsolutePath(); } /** -- cgit v1.2.3-83-g751a From 6686e63f2158eff07e39ff002ba211d0578f2a4f Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Wed, 17 Oct 2012 05:21:52 +0900 Subject: Honor automatic shift turned off for gestures Bug: 7354129 Change-Id: Ia02336e8cea2f04b629edbe74b7815cce0d7fad6 --- java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java | 4 +++- java/src/com/android/inputmethod/latin/LatinIME.java | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index e99e956e2..38025e8e4 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -389,7 +389,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { } } - public int getManualCapsMode() { + public int getKeyboardShiftMode() { final Keyboard keyboard = getKeyboard(); if (keyboard == null) { return WordComposer.CAPS_MODE_OFF; @@ -400,6 +400,8 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { return WordComposer.CAPS_MODE_MANUAL_SHIFT_LOCKED; case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED: return WordComposer.CAPS_MODE_MANUAL_SHIFTED; + case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED: + return WordComposer.CAPS_MODE_AUTO_SHIFTED; default: return WordComposer.CAPS_MODE_OFF; } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index d98966e96..cd20ba3a3 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1119,8 +1119,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // Factor in auto-caps and manual caps and compute the current caps mode. private int getActualCapsMode() { - final int manual = mKeyboardSwitcher.getManualCapsMode(); - if (manual != WordComposer.CAPS_MODE_OFF) return manual; + final int keyboardShiftMode = mKeyboardSwitcher.getKeyboardShiftMode(); + if (keyboardShiftMode != WordComposer.CAPS_MODE_AUTO_SHIFTED) return keyboardShiftMode; final int auto = getCurrentAutoCapsState(); if (0 != (auto & TextUtils.CAP_MODE_CHARACTERS)) { return WordComposer.CAPS_MODE_AUTO_SHIFT_LOCKED; -- cgit v1.2.3-83-g751a From bdc8b9e42b90e1fdf8e15d7ee5c0d319934fec0a Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Tue, 16 Oct 2012 13:26:45 -0700 Subject: Fix more suggestions text width calculation Bug: 7345983 Change-Id: Ic1554db98e7aaf032eb90a98c0c37c7c789461b5 --- java/src/com/android/inputmethod/keyboard/KeyboardView.java | 3 ++- .../com/android/inputmethod/latin/suggestions/MoreSuggestions.java | 4 +++- .../android/inputmethod/latin/suggestions/MoreSuggestionsView.java | 4 ++++ 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index b39f2bad3..472f74b12 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -105,7 +105,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { private static final String TAG = KeyboardView.class.getSimpleName(); // XML attributes - private final KeyVisualAttributes mKeyVisualAttributes; + protected final KeyVisualAttributes mKeyVisualAttributes; private final int mKeyLabelHorizontalPadding; private final float mKeyHintLetterPadding; private final float mKeyPopupHintLetterPadding; @@ -733,6 +733,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { return width; } + // TODO: Remove this method. public float getLabelWidth(final String label, final Paint paint) { paint.getTextBounds(label, 0, label.length(), mTextBounds); return mTextBounds.width(); diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java index e9bf0fac4..4e9fd1968 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java @@ -51,10 +51,11 @@ public final class MoreSuggestions extends Keyboard { super(); } + // TODO: Remove {@link MoreSuggestionsView} argument. public int layout(final SuggestedWords suggestions, final int fromPos, final int maxWidth, final int minWidth, final int maxRow, final MoreSuggestionsView view) { clearKeys(); - final Resources res = view.getContext().getResources(); + final Resources res = view.getResources(); mDivider = res.getDrawable(R.drawable.more_suggestions_divider); mDividerWidth = mDivider.getIntrinsicWidth(); final int padding = (int) res.getDimension( @@ -181,6 +182,7 @@ public final class MoreSuggestions extends Keyboard { load(xmlId, keyboard.mId); mParams.mVerticalGap = mParams.mTopPadding = keyboard.mVerticalGap / 2; + mPaneView.updateKeyboardGeometry(mParams.mDefaultRowHeight); final int count = mParams.layout(suggestions, fromPos, maxWidth, minWidth, maxRow, mPaneView); mFromPos = fromPos; diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java index 9b9a35478..03a2e73d1 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java @@ -105,6 +105,10 @@ public final class MoreSuggestionsView extends KeyboardView implements MoreKeysP } } + public void updateKeyboardGeometry(final int keyHeight) { + mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes); + } + @Override public void setKeyboard(Keyboard keyboard) { super.setKeyboard(keyboard); -- cgit v1.2.3-83-g751a From e91d495c53a2606962159cfddada2b7a5e206c4c Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Wed, 17 Oct 2012 06:41:15 +0900 Subject: Have "no whitespace before cursor" upon gesture trigger phantom space Bug: 7359291 Bug: 7357758 Bug: 7197651 Change-Id: Ia805a87e922739ae0a06978a3bf00d91c94b6c51 --- java/src/com/android/inputmethod/latin/LatinIME.java | 8 ++++++++ java/src/com/android/inputmethod/latin/RichInputConnection.java | 7 +++++++ 2 files changed, 15 insertions(+) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index d98966e96..c1c5112a1 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1429,6 +1429,12 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // The following is necessary for the case where the user typed something but didn't // manual pick it and didn't input any separator. mSpaceState = SPACE_STATE_PHANTOM; + } else { + final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor(); + if (Constants.NOT_A_CODE != codePointBeforeCursor + && !Character.isWhitespace(codePointBeforeCursor)) { + mSpaceState = SPACE_STATE_PHANTOM; + } } mConnection.endBatchEdit(); mWordComposer.setCapitalizedModeAtStartComposingTime(getActualCapsMode()); @@ -1564,6 +1570,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // We have a TLD (or something that looks like this): make sure we don't add // a space even if currently in phantom mode. mSpaceState = SPACE_STATE_NONE; + // TODO: use getCodePointBeforeCursor instead to improve performance and simplify the code final CharSequence lastOne = mConnection.getTextBeforeCursor(1, 0); if (lastOne != null && lastOne.length() == 1 && lastOne.charAt(0) == Keyboard.CODE_PERIOD) { @@ -2284,6 +2291,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // This is a stopgap solution to avoid leaving a high surrogate alone in a text view. // In the future, we need to deprecate deteleSurroundingText() and have a surrogate // pair-friendly way of deleting characters in InputConnection. + // TODO: use getCodePointBeforeCursor instead to improve performance final CharSequence lastChar = mConnection.getTextBeforeCursor(1, 0); if (!TextUtils.isEmpty(lastChar) && Character.isHighSurrogate(lastChar.charAt(0))) { mConnection.deleteSurroundingText(1, 0); diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index b27db579f..21441369e 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -235,7 +235,14 @@ public final class RichInputConnection { hasSpaceBefore); } + public int getCodePointBeforeCursor() { + if (mCommittedTextBeforeComposingText.length() < 1) return Constants.NOT_A_CODE; + return Character.codePointBefore(mCommittedTextBeforeComposingText, + mCommittedTextBeforeComposingText.length()); + } + public CharSequence getTextBeforeCursor(final int i, final int j) { + // TODO: use mCommittedTextBeforeComposingText if possible to improve performance mIC = mParent.getCurrentInputConnection(); if (null != mIC) return mIC.getTextBeforeCursor(i, j); return null; -- cgit v1.2.3-83-g751a From 8e360c68f1861a70fdb91652334efa513e25fcd2 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Mon, 15 Oct 2012 13:59:35 -0700 Subject: Move AudioAndHapticFeedbackManager from LatinIME to KeyboardSwitcher Bug: 7313372 Change-Id: I9bd3275f57ed3f5c2c4a95768443af505513ee97 --- .../inputmethod/keyboard/KeyboardSwitcher.java | 12 ++++++++++-- .../latin/AudioAndHapticFeedbackManager.java | 22 ++++++++++++---------- .../com/android/inputmethod/latin/LatinIME.java | 12 +----------- 3 files changed, 23 insertions(+), 23 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index 38025e8e4..7e0ea1699 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -29,6 +29,7 @@ import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; import com.android.inputmethod.keyboard.KeyboardLayoutSet.KeyboardLayoutSetException; import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; import com.android.inputmethod.keyboard.internal.KeyboardState; +import com.android.inputmethod.latin.AudioAndHapticFeedbackManager; import com.android.inputmethod.latin.DebugSettings; import com.android.inputmethod.latin.ImfUtils; import com.android.inputmethod.latin.InputView; @@ -65,6 +66,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { new KeyboardTheme(5, R.style.KeyboardTheme_IceCreamSandwich), }; + private AudioAndHapticFeedbackManager mFeedbackManager; private SubtypeSwitcher mSubtypeSwitcher; private SharedPreferences mPrefs; private boolean mForceNonDistinctMultitouch; @@ -102,6 +104,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { private void initInternal(LatinIME latinIme, SharedPreferences prefs) { mLatinIME = latinIme; mResources = latinIme.getResources(); + mFeedbackManager = new AudioAndHapticFeedbackManager(latinIme); mPrefs = prefs; mSubtypeSwitcher = SubtypeSwitcher.getInstance(); mState = new KeyboardState(this); @@ -147,6 +150,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { mKeyboardLayoutSet = builder.build(); try { mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols)); + mFeedbackManager.onSettingsChanged(settingsValues); } catch (KeyboardLayoutSetException e) { Log.w(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause()); LatinImeLogger.logOnException(e.mKeyboardId.toString(), e.getCause()); @@ -154,6 +158,10 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { } } + public void onRingerModeChanged() { + mFeedbackManager.onRingerModeChanged(); + } + public void saveKeyboardState() { if (getKeyboard() != null) { mState.onSaveKeyboardState(); @@ -202,7 +210,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { public void onPressKey(int code) { if (isVibrateAndSoundFeedbackRequired()) { - mLatinIME.hapticAndAudioFeedback(code); + mFeedbackManager.hapticAndAudioFeedback(code, mKeyboardView); } mState.onPressKey(code, isSinglePointer(), mLatinIME.getCurrentAutoCapsState()); } @@ -314,7 +322,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { // Implements {@link KeyboardState.SwitchActions}. @Override public void hapticAndAudioFeedback(int code) { - mLatinIME.hapticAndAudioFeedback(code); + mFeedbackManager.hapticAndAudioFeedback(code, mKeyboardView); } public void onLongPressTimeout(int code) { diff --git a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java index 59ef5e09f..91bbd54c7 100644 --- a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java +++ b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java @@ -31,17 +31,15 @@ import com.android.inputmethod.latin.VibratorUtils; * complexity of settings and the like. */ public final class AudioAndHapticFeedbackManager { - final private SettingsValues mSettingsValues; - final private AudioManager mAudioManager; - final private VibratorUtils mVibratorUtils; + private final AudioManager mAudioManager; + private final VibratorUtils mVibratorUtils; + + private SettingsValues mSettingsValues; private boolean mSoundOn; - public AudioAndHapticFeedbackManager(final LatinIME latinIme, - final SettingsValues settingsValues) { - mSettingsValues = settingsValues; + public AudioAndHapticFeedbackManager(final LatinIME latinIme) { mVibratorUtils = VibratorUtils.getInstance(latinIme); mAudioManager = (AudioManager) latinIme.getSystemService(Context.AUDIO_SERVICE); - mSoundOn = reevaluateIfSoundIsOn(); } public void hapticAndAudioFeedback(final int primaryCode, @@ -51,7 +49,7 @@ public final class AudioAndHapticFeedbackManager { } private boolean reevaluateIfSoundIsOn() { - if (!mSettingsValues.mSoundOn || mAudioManager == null) { + if (mSettingsValues == null || !mSettingsValues.mSoundOn || mAudioManager == null) { return false; } else { return mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL; @@ -81,8 +79,7 @@ public final class AudioAndHapticFeedbackManager { } } - // TODO: make this private when LatinIME does not call it any more - public void vibrate(final View viewToPerformHapticFeedbackOn) { + private void vibrate(final View viewToPerformHapticFeedbackOn) { if (!mSettingsValues.mVibrateOn) { return; } @@ -98,6 +95,11 @@ public final class AudioAndHapticFeedbackManager { } } + public void onSettingsChanged(final SettingsValues settingsValues) { + mSettingsValues = settingsValues; + mSoundOn = reevaluateIfSoundIsOn(); + } + public void onRingerModeChanged() { mSoundOn = reevaluateIfSoundIsOn(); } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 044d6de18..4cf6a5112 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -163,8 +163,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction private int mDeleteCount; private long mLastKeyTime; - private AudioAndHapticFeedbackManager mFeedbackManager; - // Member variables for remembering the current device orientation. private int mDisplayOrientation; @@ -438,7 +436,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction } }; mCurrentSettings = job.runInLocale(mResources, mSubtypeSwitcher.getCurrentSubtypeLocale()); - mFeedbackManager = new AudioAndHapticFeedbackManager(this, mCurrentSettings); resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary()); } @@ -2251,13 +2248,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction mHandler.postUpdateSuggestionStrip(); } - // TODO: Remove this method from {@link LatinIME} and move {@link FeedbackManager} to - // {@link KeyboardSwitcher}. Called from KeyboardSwitcher - public void hapticAndAudioFeedback(final int primaryCode) { - mFeedbackManager.hapticAndAudioFeedback( - primaryCode, mKeyboardSwitcher.getMainKeyboardView()); - } - // Callback called by PointerTracker through the KeyboardActionListener. This is called when a // key is depressed; release matching call is onReleaseKey below. @Override @@ -2303,7 +2293,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { mSubtypeSwitcher.onNetworkStateChanged(intent); } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { - mFeedbackManager.onRingerModeChanged(); + mKeyboardSwitcher.onRingerModeChanged(); } } }; -- cgit v1.2.3-83-g751a From 5faf41951929301af80026bc3191812ef874fd5a Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Mon, 15 Oct 2012 13:59:35 -0700 Subject: Suggestion strip will honor haptic feedback settings of keyboard Bug: 7313372 Change-Id: I427da8de68be3d2a78e810556340b96ab4edcc2d --- java/res/layout/suggestion_word.xml | 3 +++ .../com/android/inputmethod/latin/suggestions/SuggestionStripView.java | 2 ++ 2 files changed, 5 insertions(+) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/res/layout/suggestion_word.xml b/java/res/layout/suggestion_word.xml index d64cacf04..fa00e041e 100644 --- a/java/res/layout/suggestion_word.xml +++ b/java/res/layout/suggestion_word.xml @@ -18,6 +18,8 @@ */ --> + Date: Wed, 3 Oct 2012 15:19:43 +0900 Subject: Replace useless CharSequence to String Change-Id: Idc478f901185ee1b4912acc82d0cbc54fee4e991 --- .../inputmethod/compat/SuggestionSpanUtils.java | 19 ++-- .../keyboard/KeyboardActionListener.java | 10 +- .../inputmethod/keyboard/MoreKeysKeyboardView.java | 32 ++++--- .../android/inputmethod/latin/AutoCorrection.java | 23 +++-- .../inputmethod/latin/BinaryDictionary.java | 28 +++--- .../latin/ContactsBinaryDictionary.java | 15 +-- .../com/android/inputmethod/latin/Dictionary.java | 10 +- .../inputmethod/latin/DictionaryCollection.java | 6 +- .../latin/ExpandableBinaryDictionary.java | 14 +-- .../inputmethod/latin/ExpandableDictionary.java | 50 +++++----- .../inputmethod/latin/LastComposedWord.java | 4 +- .../com/android/inputmethod/latin/LatinIME.java | 54 ++++++----- .../inputmethod/latin/RichInputConnection.java | 30 +++--- .../com/android/inputmethod/latin/StringUtils.java | 104 +++++---------------- .../src/com/android/inputmethod/latin/Suggest.java | 39 ++++---- .../android/inputmethod/latin/SuggestedWords.java | 25 ++--- ...ynchronouslyLoadedContactsBinaryDictionary.java | 4 +- .../SynchronouslyLoadedUserBinaryDictionary.java | 4 +- .../inputmethod/latin/UserBinaryDictionary.java | 2 +- .../inputmethod/latin/UserHistoryDictionary.java | 24 ++--- .../android/inputmethod/latin/WordComposer.java | 19 ++-- .../spellcheck/AndroidSpellCheckerService.java | 4 +- .../AndroidWordLevelSpellCheckerSession.java | 2 +- .../latin/spellcheck/DictionaryPool.java | 4 +- .../latin/suggestions/MoreSuggestions.java | 2 +- .../latin/suggestions/SuggestionStripView.java | 18 ++-- .../android/inputmethod/latin/InputTestsBase.java | 2 +- 27 files changed, 249 insertions(+), 299 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java index 9a89eedd0..c1609ea28 100644 --- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java +++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java @@ -83,14 +83,13 @@ public final class SuggestionSpanUtils { } public static CharSequence getTextWithAutoCorrectionIndicatorUnderline( - Context context, CharSequence text) { + final Context context, final String text) { if (TextUtils.isEmpty(text) || CONSTRUCTOR_SuggestionSpan == null || OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null || OBJ_FLAG_MISSPELLED == null || OBJ_FLAG_EASY_CORRECT == null) { return text; } - final Spannable spannable = text instanceof Spannable - ? (Spannable) text : new SpannableString(text); + final Spannable spannable = new SpannableString(text); final Object[] args = { context, null, new String[] {}, (int)OBJ_FLAG_AUTO_CORRECTION, (Class) SuggestionSpanPickedNotificationReceiver.class }; @@ -104,8 +103,9 @@ public final class SuggestionSpanUtils { return spannable; } - public static CharSequence getTextWithSuggestionSpan(Context context, - CharSequence pickedWord, SuggestedWords suggestedWords, boolean dictionaryAvailable) { + public static CharSequence getTextWithSuggestionSpan(final Context context, + final String pickedWord, final SuggestedWords suggestedWords, + final boolean dictionaryAvailable) { if (!dictionaryAvailable || TextUtils.isEmpty(pickedWord) || CONSTRUCTOR_SuggestionSpan == null || suggestedWords.isEmpty() || suggestedWords.mIsPrediction @@ -114,18 +114,13 @@ public final class SuggestionSpanUtils { return pickedWord; } - final Spannable spannable; - if (pickedWord instanceof Spannable) { - spannable = (Spannable) pickedWord; - } else { - spannable = new SpannableString(pickedWord); - } + final Spannable spannable = new SpannableString(pickedWord); final ArrayList suggestionsList = CollectionUtils.newArrayList(); for (int i = 0; i < suggestedWords.size(); ++i) { if (suggestionsList.size() >= OBJ_SUGGESTIONS_MAX_SIZE) { break; } - final CharSequence word = suggestedWords.getWord(i); + final String word = suggestedWords.getWord(i); if (!TextUtils.equals(pickedWord, word)) { suggestionsList.add(word.toString()); } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java index 5c8f78f5e..e7a4e82a2 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java @@ -56,11 +56,11 @@ public interface KeyboardActionListener { public void onCodeInput(int primaryCode, int x, int y); /** - * Sends a sequence of characters to the listener. + * Sends a string of characters to the listener. * - * @param text the sequence of characters to be displayed. + * @param text the string of characters to be registered. */ - public void onTextInput(CharSequence text); + public void onTextInput(String text); /** * Called when user started batch input. @@ -99,7 +99,7 @@ public interface KeyboardActionListener { @Override public void onCodeInput(int primaryCode, int x, int y) {} @Override - public void onTextInput(CharSequence text) {} + public void onTextInput(String text) {} @Override public void onStartBatchInput() {} @Override @@ -114,7 +114,7 @@ public interface KeyboardActionListener { } // TODO: Remove this method when the vertical correction is removed. - public static boolean isInvalidCoordinate(int coordinate) { + public static boolean isInvalidCoordinate(final int coordinate) { // Detect {@link Constants#NOT_A_COORDINATE}, // {@link Constants#SUGGESTION_STRIP_COORDINATE}, and // {@link Constants#SPELL_CHECKER_COORDINATE}. diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java index a50617693..9c450e994 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java @@ -48,7 +48,7 @@ public final class MoreKeysKeyboardView extends KeyboardView implements MoreKeys private final KeyboardActionListener mMoreKeysKeyboardListener = new KeyboardActionListener.Adapter() { @Override - public void onCodeInput(int primaryCode, int x, int y) { + public void onCodeInput(final int primaryCode, final int x, final int y) { // Because a more keys keyboard doesn't need proximity characters correction, we don't // send touch event coordinates. mListener.onCodeInput( @@ -56,7 +56,7 @@ public final class MoreKeysKeyboardView extends KeyboardView implements MoreKeys } @Override - public void onTextInput(CharSequence text) { + public void onTextInput(final String text) { mListener.onTextInput(text); } @@ -66,12 +66,12 @@ public final class MoreKeysKeyboardView extends KeyboardView implements MoreKeys } @Override - public void onUpdateBatchInput(InputPointers batchPointers) { + public void onUpdateBatchInput(final InputPointers batchPointers) { mListener.onUpdateBatchInput(batchPointers); } @Override - public void onEndBatchInput(InputPointers batchPointers) { + public void onEndBatchInput(final InputPointers batchPointers) { mListener.onEndBatchInput(batchPointers); } @@ -81,21 +81,22 @@ public final class MoreKeysKeyboardView extends KeyboardView implements MoreKeys } @Override - public void onPressKey(int primaryCode) { + public void onPressKey(final int primaryCode) { mListener.onPressKey(primaryCode); } @Override - public void onReleaseKey(int primaryCode, boolean withSliding) { + public void onReleaseKey(final int primaryCode, final boolean withSliding) { mListener.onReleaseKey(primaryCode, withSliding); } }; - public MoreKeysKeyboardView(Context context, AttributeSet attrs) { + public MoreKeysKeyboardView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.moreKeysKeyboardViewStyle); } - public MoreKeysKeyboardView(Context context, AttributeSet attrs, int defStyle) { + public MoreKeysKeyboardView(final Context context, final AttributeSet attrs, + final int defStyle) { super(context, attrs, defStyle); final Resources res = context.getResources(); @@ -105,7 +106,7 @@ public final class MoreKeysKeyboardView extends KeyboardView implements MoreKeys } @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Keyboard keyboard = getKeyboard(); if (keyboard != null) { final int width = keyboard.mOccupiedWidth + getPaddingLeft() + getPaddingRight(); @@ -117,7 +118,7 @@ public final class MoreKeysKeyboardView extends KeyboardView implements MoreKeys } @Override - public void setKeyboard(Keyboard keyboard) { + public void setKeyboard(final Keyboard keyboard) { super.setKeyboard(keyboard); mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(), -getPaddingTop() + mVerticalCorrection); @@ -144,15 +145,16 @@ public final class MoreKeysKeyboardView extends KeyboardView implements MoreKeys } @Override - public void setKeyPreviewPopupEnabled(boolean previewEnabled, int delay) { + public void setKeyPreviewPopupEnabled(final boolean previewEnabled, final int delay) { // More keys keyboard needs no pop-up key preview displayed, so we pass always false with a // delay of 0. The delay does not matter actually since the popup is not shown anyway. super.setKeyPreviewPopupEnabled(false, 0); } @Override - public void showMoreKeysPanel(View parentView, Controller controller, int pointX, int pointY, - PopupWindow window, KeyboardActionListener listener) { + public void showMoreKeysPanel(final View parentView, final Controller controller, + final int pointX, final int pointY, final PopupWindow window, + final KeyboardActionListener listener) { mController = controller; mListener = listener; final View container = (View)getParent(); @@ -185,12 +187,12 @@ public final class MoreKeysKeyboardView extends KeyboardView implements MoreKeys } @Override - public int translateX(int x) { + public int translateX(final int x) { return x - mOriginX; } @Override - public int translateY(int y) { + public int translateY(final int y) { return y - mOriginY; } } diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java index 84fad158f..fa35922b0 100644 --- a/java/src/com/android/inputmethod/latin/AutoCorrection.java +++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java @@ -33,11 +33,11 @@ public final class AutoCorrection { } public static boolean isValidWord(final ConcurrentHashMap dictionaries, - CharSequence word, boolean ignoreCase) { + final String word, final boolean ignoreCase) { if (TextUtils.isEmpty(word)) { return false; } - final CharSequence lowerCasedWord = word.toString().toLowerCase(); + final String lowerCasedWord = word.toLowerCase(); for (final String key : dictionaries.keySet()) { final Dictionary dictionary = dictionaries.get(key); // It's unclear how realistically 'dictionary' can be null, but the monkey is somehow @@ -57,7 +57,7 @@ public final class AutoCorrection { } public static int getMaxFrequency(final ConcurrentHashMap dictionaries, - CharSequence word) { + final String word) { if (TextUtils.isEmpty(word)) { return Dictionary.NOT_A_PROBABILITY; } @@ -76,12 +76,13 @@ public final class AutoCorrection { // Returns true if this is in any of the dictionaries. public static boolean isInTheDictionary( final ConcurrentHashMap dictionaries, - final CharSequence word, final boolean ignoreCase) { + final String word, final boolean ignoreCase) { return isValidWord(dictionaries, word, ignoreCase); } - public static boolean suggestionExceedsAutoCorrectionThreshold(SuggestedWordInfo suggestion, - CharSequence consideredWord, float autoCorrectionThreshold) { + public static boolean suggestionExceedsAutoCorrectionThreshold( + final SuggestedWordInfo suggestion, final String consideredWord, + final float autoCorrectionThreshold) { if (null != suggestion) { // Shortlist a whitelisted word if (suggestion.mKind == SuggestedWordInfo.KIND_WHITELIST) return true; @@ -89,8 +90,7 @@ public final class AutoCorrection { // TODO: when the normalized score of the first suggestion is nearly equals to // the normalized score of the second suggestion, behave less aggressive. final float normalizedScore = BinaryDictionary.calcNormalizedScore( - consideredWord.toString(), suggestion.mWord.toString(), - autoCorrectionSuggestionScore); + consideredWord, suggestion.mWord, autoCorrectionSuggestionScore); if (DBG) { Log.d(TAG, "Normalized " + consideredWord + "," + suggestion + "," + autoCorrectionSuggestionScore + ", " + normalizedScore @@ -100,8 +100,7 @@ public final class AutoCorrection { if (DBG) { Log.d(TAG, "Auto corrected by S-threshold."); } - return !shouldBlockAutoCorrectionBySafetyNet(consideredWord.toString(), - suggestion.mWord); + return !shouldBlockAutoCorrectionBySafetyNet(consideredWord, suggestion.mWord); } } return false; @@ -110,7 +109,7 @@ public final class AutoCorrection { // TODO: Resolve the inconsistencies between the native auto correction algorithms and // this safety net public static boolean shouldBlockAutoCorrectionBySafetyNet(final String typedWord, - final CharSequence suggestion) { + final String suggestion) { // Safety net for auto correction. // Actually if we hit this safety net, it's a bug. // If user selected aggressive auto correction mode, there is no need to use the safety @@ -123,7 +122,7 @@ public final class AutoCorrection { } final int maxEditDistanceOfNativeDictionary = (typedWordLength < 5 ? 2 : typedWordLength / 2) + 1; - final int distance = BinaryDictionary.editDistance(typedWord, suggestion.toString()); + final int distance = BinaryDictionary.editDistance(typedWord, suggestion); if (DBG) { Log.d(TAG, "Autocorrected edit distance = " + distance + ", " + maxEditDistanceOfNativeDictionary); diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 9c48aa1a4..e4275de19 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -64,7 +64,7 @@ public final class BinaryDictionary extends Dictionary { // TODO: There should be a way to remove used DicTraverseSession objects from // {@code mDicTraverseSessions}. - private DicTraverseSession getTraverseSession(int traverseSessionId) { + private DicTraverseSession getTraverseSession(final int traverseSessionId) { synchronized(mDicTraverseSessions) { DicTraverseSession traverseSession = mDicTraverseSessions.get(traverseSessionId); if (traverseSession == null) { @@ -116,26 +116,27 @@ public final class BinaryDictionary extends Dictionary { private static native int editDistanceNative(char[] before, char[] after); // TODO: Move native dict into session - private final void loadDictionary(String path, long startOffset, long length) { + private final void loadDictionary(final String path, final long startOffset, + final long length) { mNativeDict = openNative(path, startOffset, length, FULL_WORD_SCORE_MULTIPLIER, MAX_WORD_LENGTH, MAX_WORDS, MAX_PREDICTIONS); } @Override public ArrayList getSuggestions(final WordComposer composer, - final CharSequence prevWord, final ProximityInfo proximityInfo) { + final String prevWord, final ProximityInfo proximityInfo) { return getSuggestionsWithSessionId(composer, prevWord, proximityInfo, 0); } @Override public ArrayList getSuggestionsWithSessionId(final WordComposer composer, - final CharSequence prevWord, final ProximityInfo proximityInfo, int sessionId) { + final String prevWord, final ProximityInfo proximityInfo, int sessionId) { if (!isValidDictionary()) return null; Arrays.fill(mInputCodePoints, Constants.NOT_A_CODE); // TODO: toLowerCase in the native code final int[] prevWordCodePointArray = (null == prevWord) - ? null : StringUtils.toCodePointArray(prevWord.toString()); + ? null : StringUtils.toCodePointArray(prevWord); final int composerSize = composer.size(); final boolean isGesture = composer.isBatchMode(); @@ -178,11 +179,12 @@ public final class BinaryDictionary extends Dictionary { return mNativeDict != 0; } - public static float calcNormalizedScore(String before, String after, int score) { + public static float calcNormalizedScore(final String before, final String after, + final int score) { return calcNormalizedScoreNative(before.toCharArray(), after.toCharArray(), score); } - public static int editDistance(String before, String after) { + public static int editDistance(final String before, final String after) { if (before == null || after == null) { throw new IllegalArgumentException(); } @@ -190,23 +192,23 @@ public final class BinaryDictionary extends Dictionary { } @Override - public boolean isValidWord(CharSequence word) { + public boolean isValidWord(final String word) { return getFrequency(word) >= 0; } @Override - public int getFrequency(CharSequence word) { + public int getFrequency(final String word) { if (word == null) return -1; - int[] codePoints = StringUtils.toCodePointArray(word.toString()); + int[] codePoints = StringUtils.toCodePointArray(word); return getFrequencyNative(mNativeDict, codePoints); } // TODO: Add a batch process version (isValidBigramMultiple?) to avoid excessive numbers of jni // calls when checking for changes in an entire dictionary. - public boolean isValidBigram(CharSequence word1, CharSequence word2) { + public boolean isValidBigram(final String word1, final String word2) { if (TextUtils.isEmpty(word1) || TextUtils.isEmpty(word2)) return false; - int[] chars1 = StringUtils.toCodePointArray(word1.toString()); - int[] chars2 = StringUtils.toCodePointArray(word2.toString()); + final int[] chars1 = StringUtils.toCodePointArray(word1); + final int[] chars2 = StringUtils.toCodePointArray(word2); return isValidBigramNative(mNativeDict, chars1, chars2); } diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java index 5edc4314f..7c0448024 100644 --- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java @@ -62,7 +62,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { */ private final boolean mUseFirstLastBigrams; - public ContactsBinaryDictionary(final Context context, Locale locale) { + public ContactsBinaryDictionary(final Context context, final Locale locale) { super(context, getFilenameWithLocale(NAME, locale.toString()), Dictionary.TYPE_CONTACTS); mLocale = locale; mUseFirstLastBigrams = useFirstLastBigramsForLocale(locale); @@ -120,7 +120,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { } } - private boolean useFirstLastBigramsForLocale(Locale locale) { + private 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; @@ -128,7 +128,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { return false; } - private void addWords(Cursor cursor) { + private void addWords(final Cursor cursor) { clearFusionDictionary(); int count = 0; while (!cursor.isAfterLast() && count < MAX_CONTACT_COUNT) { @@ -160,7 +160,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { * Adds the words in a name (e.g., firstname/lastname) to the binary dictionary along with their * bigrams depending on locale. */ - private void addName(String name) { + private void addName(final String name) { int len = StringUtils.codePointCount(name); String prevWord = null; // TODO: Better tokenization for non-Latin writing systems @@ -188,7 +188,8 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { /** * Returns the index of the last letter in the word, starting from position startIndex. */ - private static int getWordEndPosition(String string, int len, int startIndex) { + private static int getWordEndPosition(final String string, final int len, + final int startIndex) { int end; int cp = 0; for (end = startIndex + 1; end < len; end += Character.charCount(cp)) { @@ -249,7 +250,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { return false; } - private static boolean isValidName(String name) { + private static boolean isValidName(final String name) { if (name != null && -1 == name.indexOf('@')) { return true; } @@ -259,7 +260,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { /** * Checks if the words in a name are in the current binary dictionary. */ - private boolean isNameInDictionary(String name) { + private boolean isNameInDictionary(final String name) { int len = StringUtils.codePointCount(name); String prevWord = null; for (int i = 0; i < len; i++) { diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java index 88d0c09dd..8207bc47f 100644 --- a/java/src/com/android/inputmethod/latin/Dictionary.java +++ b/java/src/com/android/inputmethod/latin/Dictionary.java @@ -59,12 +59,12 @@ public abstract class Dictionary { // TODO: pass more context than just the previous word, to enable better suggestions (n-gram // and more) abstract public ArrayList getSuggestions(final WordComposer composer, - final CharSequence prevWord, final ProximityInfo proximityInfo); + final String prevWord, final ProximityInfo proximityInfo); // The default implementation of this method ignores sessionId. // Subclasses that want to use sessionId need to override this method. public ArrayList getSuggestionsWithSessionId(final WordComposer composer, - final CharSequence prevWord, final ProximityInfo proximityInfo, int sessionId) { + final String prevWord, final ProximityInfo proximityInfo, final int sessionId) { return getSuggestions(composer, prevWord, proximityInfo); } @@ -73,9 +73,9 @@ public abstract class Dictionary { * @param word the word to search for. The search should be case-insensitive. * @return true if the word exists, false otherwise */ - abstract public boolean isValidWord(CharSequence word); + abstract public boolean isValidWord(final String word); - public int getFrequency(CharSequence word) { + public int getFrequency(final String word) { return NOT_A_PROBABILITY; } @@ -87,7 +87,7 @@ public abstract class Dictionary { * @param typedWord the word to compare with * @return true if they are the same, false otherwise. */ - protected boolean same(final char[] word, final int length, final CharSequence typedWord) { + protected boolean same(final char[] word, final int length, final String typedWord) { if (typedWord.length() != length) { return false; } diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java index d3b120989..7f78ac8a2 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java +++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java @@ -56,7 +56,7 @@ public final class DictionaryCollection extends Dictionary { @Override public ArrayList getSuggestions(final WordComposer composer, - final CharSequence prevWord, final ProximityInfo proximityInfo) { + final String prevWord, final ProximityInfo proximityInfo) { final CopyOnWriteArrayList dictionaries = mDictionaries; if (dictionaries.isEmpty()) return null; // To avoid creating unnecessary objects, we get the list out of the first @@ -74,14 +74,14 @@ public final class DictionaryCollection extends Dictionary { } @Override - public boolean isValidWord(CharSequence word) { + public boolean isValidWord(final String word) { for (int i = mDictionaries.size() - 1; i >= 0; --i) if (mDictionaries.get(i).isValidWord(word)) return true; return false; } @Override - public int getFrequency(CharSequence word) { + public int getFrequency(final String word) { int maxFreq = -1; for (int i = mDictionaries.size() - 1; i >= 0; --i) { final int tempFreq = mDictionaries.get(i).getFrequency(word); diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index b93c17f11..159867ade 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -198,7 +198,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { @Override public ArrayList getSuggestions(final WordComposer composer, - final CharSequence prevWord, final ProximityInfo proximityInfo) { + final String prevWord, final ProximityInfo proximityInfo) { asyncReloadDictionaryIfRequired(); if (mLocalDictionaryController.tryLock()) { try { @@ -213,12 +213,12 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } @Override - public boolean isValidWord(final CharSequence word) { + public boolean isValidWord(final String word) { asyncReloadDictionaryIfRequired(); return isValidWordInner(word); } - protected boolean isValidWordInner(final CharSequence word) { + protected boolean isValidWordInner(final String word) { if (mLocalDictionaryController.tryLock()) { try { return isValidWordLocked(word); @@ -229,17 +229,17 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { return false; } - protected boolean isValidWordLocked(final CharSequence word) { + protected boolean isValidWordLocked(final String word) { if (mBinaryDictionary == null) return false; return mBinaryDictionary.isValidWord(word); } - protected boolean isValidBigram(final CharSequence word1, final CharSequence word2) { + protected boolean isValidBigram(final String word1, final String word2) { if (mBinaryDictionary == null) return false; return mBinaryDictionary.isValidBigram(word1, word2); } - protected boolean isValidBigramInner(final CharSequence word1, final CharSequence word2) { + protected boolean isValidBigramInner(final String word1, final String word2) { if (mLocalDictionaryController.tryLock()) { try { return isValidBigramLocked(word1, word2); @@ -250,7 +250,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { return false; } - protected boolean isValidBigramLocked(final CharSequence word1, final CharSequence word2) { + protected boolean isValidBigramLocked(final String word1, final String word2) { if (mBinaryDictionary == null) return false; return mBinaryDictionary.isValidBigram(word1, word2); } diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java index 8cdc2a0af..c96a802ce 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -69,7 +69,7 @@ public class ExpandableDictionary extends Dictionary { mData = new Node[INCREMENT]; } - void add(Node n) { + void add(final Node n) { if (mLength + 1 > mData.length) { Node[] tempData = new Node[mLength + INCREMENT]; if (mLength > 0) { @@ -172,7 +172,7 @@ public class ExpandableDictionary extends Dictionary { } } - public void setRequiresReload(boolean reload) { + public void setRequiresReload(final boolean reload) { synchronized (mUpdatingLock) { mRequiresReload = reload; } @@ -202,8 +202,8 @@ public class ExpandableDictionary extends Dictionary { addWordRec(mRoots, word, 0, shortcutTarget, frequency, null); } - private void addWordRec(NodeArray children, final String word, final int depth, - final String shortcutTarget, final int frequency, Node parentNode) { + private void addWordRec(final NodeArray children, final String word, final int depth, + final String shortcutTarget, final int frequency, final Node parentNode) { final int wordLength = word.length(); if (wordLength <= depth) return; final char c = word.charAt(depth); @@ -248,7 +248,7 @@ public class ExpandableDictionary extends Dictionary { @Override public ArrayList getSuggestions(final WordComposer composer, - final CharSequence prevWord, final ProximityInfo proximityInfo) { + final String prevWord, final ProximityInfo proximityInfo) { if (reloadDictionaryIfRequired()) return null; if (composer.size() > 1) { if (composer.size() >= BinaryDictionary.MAX_WORD_LENGTH) { @@ -277,7 +277,7 @@ public class ExpandableDictionary extends Dictionary { } protected ArrayList getWordsInner(final WordComposer codes, - final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) { + final String prevWordForBigrams, final ProximityInfo proximityInfo) { final ArrayList suggestions = CollectionUtils.newArrayList(); mInputLength = codes.size(); if (mCodes.length < mInputLength) mCodes = new int[mInputLength][]; @@ -305,7 +305,7 @@ public class ExpandableDictionary extends Dictionary { } @Override - public synchronized boolean isValidWord(CharSequence word) { + public synchronized boolean isValidWord(final String word) { synchronized (mUpdatingLock) { // If we need to update, start off a background task if (mRequiresReload) startDictionaryLoadingTaskLocked(); @@ -320,7 +320,7 @@ public class ExpandableDictionary extends Dictionary { return (node == null) ? false : !node.mShortcutOnly; } - protected boolean removeBigram(String word1, String word2) { + protected boolean removeBigram(final String word1, final String word2) { // Refer to addOrSetBigram() about word1.toLowerCase() final Node firstWord = searchWord(mRoots, word1.toLowerCase(), 0, null); final Node secondWord = searchWord(mRoots, word2, 0, null); @@ -345,13 +345,13 @@ public class ExpandableDictionary extends Dictionary { /** * Returns the word's frequency or -1 if not found */ - protected int getWordFrequency(CharSequence word) { + protected int getWordFrequency(final String word) { // Case-sensitive search final Node node = searchNode(mRoots, word, 0, word.length()); return (node == null) ? -1 : node.mFrequency; } - protected NextWord getBigramWord(String word1, String word2) { + protected NextWord getBigramWord(final String word1, final String word2) { // Refer to addOrSetBigram() about word1.toLowerCase() final Node firstWord = searchWord(mRoots, word1.toLowerCase(), 0, null); final Node secondWord = searchWord(mRoots, word2, 0, null); @@ -368,7 +368,8 @@ public class ExpandableDictionary extends Dictionary { return null; } - private static int computeSkippedWordFinalFreq(int freq, int snr, int inputLength) { + private static int computeSkippedWordFinalFreq(final int freq, final int snr, + final int inputLength) { // The computation itself makes sense for >= 2, but the == 2 case returns 0 // anyway so we may as well test against 3 instead and return the constant if (inputLength >= 3) { @@ -431,9 +432,9 @@ public class ExpandableDictionary extends Dictionary { * @param suggestions the list in which to add suggestions */ // TODO: Share this routine with the native code for BinaryDictionary - protected void getWordsRec(NodeArray roots, final WordComposer codes, final char[] word, - final int depth, final boolean completion, int snr, int inputIndex, int skipPos, - final ArrayList suggestions) { + protected void getWordsRec(final NodeArray roots, final WordComposer codes, final char[] word, + final int depth, final boolean completion, final int snr, final int inputIndex, + final int skipPos, final ArrayList suggestions) { final int count = roots.mLength; final int codeSize = mInputLength; // Optimization: Prune out words that are too long compared to how much was typed. @@ -524,11 +525,13 @@ public class ExpandableDictionary extends Dictionary { } } - public int setBigramAndGetFrequency(String word1, String word2, int frequency) { + public int setBigramAndGetFrequency(final String word1, final String word2, + final int frequency) { return setBigramAndGetFrequency(word1, word2, frequency, null /* unused */); } - public int setBigramAndGetFrequency(String word1, String word2, ForgettingCurveParams fcp) { + public int setBigramAndGetFrequency(final String word1, final String word2, + final ForgettingCurveParams fcp) { return setBigramAndGetFrequency(word1, word2, 0 /* unused */, fcp); } @@ -540,8 +543,8 @@ public class ExpandableDictionary extends Dictionary { * @param fcp an instance of ForgettingCurveParams to use for decay policy * @return returns the final bigram frequency */ - private int setBigramAndGetFrequency( - String word1, String word2, int frequency, ForgettingCurveParams fcp) { + private int setBigramAndGetFrequency(final String word1, final String word2, + final int frequency, final ForgettingCurveParams fcp) { // We don't want results to be different according to case of the looked up left hand side // word. We do want however to return the correct case for the right hand side. // So we want to squash the case of the left hand side, and preserve that of the right @@ -572,7 +575,8 @@ public class ExpandableDictionary extends Dictionary { * Searches for the word and add the word if it does not exist. * @return Returns the terminal node of the word we are searching for. */ - private Node searchWord(NodeArray children, String word, int depth, Node parentNode) { + private Node searchWord(final NodeArray children, final String word, final int depth, + final Node parentNode) { final int wordLength = word.length(); final char c = word.charAt(depth); // Does children have the current character? @@ -602,11 +606,11 @@ public class ExpandableDictionary extends Dictionary { return searchWord(childNode.mChildren, word, depth + 1, childNode); } - private void runBigramReverseLookUp(final CharSequence previousWord, + private void runBigramReverseLookUp(final String previousWord, final ArrayList suggestions) { // Search for the lowercase version of the word only, because that's where bigrams // store their sons. - Node prevWord = searchNode(mRoots, previousWord.toString().toLowerCase(), 0, + final Node prevWord = searchNode(mRoots, previousWord.toLowerCase(), 0, previousWord.length()); if (prevWord != null && prevWord.mNGrams != null) { reverseLookUp(prevWord.mNGrams, suggestions); @@ -641,7 +645,7 @@ public class ExpandableDictionary extends Dictionary { * @param terminalNodes list of terminal nodes we want to add * @param suggestions the suggestion collection to add the word to */ - private void reverseLookUp(LinkedList terminalNodes, + private void reverseLookUp(final LinkedList terminalNodes, final ArrayList suggestions) { Node node; int freq; @@ -714,7 +718,7 @@ public class ExpandableDictionary extends Dictionary { } } - private static char toLowerCase(char c) { + private static char toLowerCase(final char c) { char baseChar = c; if (c < BASE_CHARS.length) { baseChar = BASE_CHARS[c]; diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java index 94cdc9b85..44ef01204 100644 --- a/java/src/com/android/inputmethod/latin/LastComposedWord.java +++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java @@ -44,7 +44,7 @@ public final class LastComposedWord { public final String mTypedWord; public final String mCommittedWord; public final String mSeparatorString; - public final CharSequence mPrevWord; + public final String mPrevWord; public final InputPointers mInputPointers = new InputPointers(BinaryDictionary.MAX_WORD_LENGTH); private boolean mActive; @@ -56,7 +56,7 @@ public final class LastComposedWord { // immutable. Do not fiddle with their contents after you passed them to this constructor. public LastComposedWord(final int[] primaryKeyCodes, final InputPointers inputPointers, final String typedWord, final String committedWord, - final String separatorString, final CharSequence prevWord) { + final String separatorString, final String prevWord) { mPrimaryKeyCodes = primaryKeyCodes; if (inputPointers != null) { mInputPointers.copy(inputPointers); diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 4cf6a5112..a68ff6504 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -171,7 +171,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction new DictionaryPackInstallBroadcastReceiver(this); // Keeps track of most recently inserted text (multi-character key) for reverting - private CharSequence mEnteredText; + private String mEnteredText; private boolean mIsAutoCorrectionIndicatorOn; @@ -1093,7 +1093,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction private void commitTyped(final String separatorString) { if (!mWordComposer.isComposingWord()) return; - final CharSequence typedWord = mWordComposer.getTypedWord(); + final String typedWord = mWordComposer.getTypedWord(); if (typedWord.length() > 0) { commitChosenWord(typedWord, LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, separatorString); @@ -1379,7 +1379,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // Called from PointerTracker through the KeyboardActionListener interface @Override - public void onTextInput(final CharSequence rawText) { + public void onTextInput(final String rawText) { mConnection.beginBatchEdit(); if (mWordComposer.isComposingWord()) { commitCurrentAutoCorrection(rawText.toString()); @@ -1387,7 +1387,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction resetComposingState(true /* alsoResetLastComposedWord */); } mHandler.postUpdateSuggestionStrip(); - final CharSequence text = specificTldProcessingOnTextInput(rawText); + final String text = specificTldProcessingOnTextInput(rawText); if (SPACE_STATE_PHANTOM == mSpaceState) { sendKeyCodePoint(Keyboard.CODE_SPACE); } @@ -1558,7 +1558,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction mKeyboardSwitcher.updateShiftState(); } - private CharSequence specificTldProcessingOnTextInput(final CharSequence text) { + private String specificTldProcessingOnTextInput(final String text) { if (text.length() <= 1 || text.charAt(0) != Keyboard.CODE_PERIOD || !Character.isLetter(text.charAt(1))) { // Not a tld: do nothing. @@ -1571,7 +1571,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction final CharSequence lastOne = mConnection.getTextBeforeCursor(1, 0); if (lastOne != null && lastOne.length() == 1 && lastOne.charAt(0) == Keyboard.CODE_PERIOD) { - return text.subSequence(1, text.length()); + return text.substring(1); } else { return text; } @@ -1831,7 +1831,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction return didAutoCorrect; } - private CharSequence getTextWithUnderline(final CharSequence text) { + private CharSequence getTextWithUnderline(final String text) { return mIsAutoCorrectionIndicatorOn ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(this, text) : text; @@ -1926,7 +1926,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // whatever is *before* the half-committed word in the buffer, hence 2; if we aren't, we // should just skip whitespace if any, so 1. // TODO: this is slow (2-way IPC) - we should probably cache this instead. - final CharSequence prevWord = + final String prevWord = mConnection.getNthPreviousWord(mCurrentSettings.mWordSeparators, mWordComposer.isComposingWord() ? 2 : 1); final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer, @@ -1935,7 +1935,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction return maybeRetrieveOlderSuggestions(typedWord, suggestedWords); } - private SuggestedWords maybeRetrieveOlderSuggestions(final CharSequence typedWord, + private SuggestedWords maybeRetrieveOlderSuggestions(final String typedWord, final SuggestedWords suggestedWords) { // TODO: consolidate this into getSuggestedWords // We update the suggestion strip only when we have some suggestions to show, i.e. when @@ -1965,13 +1965,12 @@ public final class LatinIME extends InputMethodService implements KeyboardAction } } - private void showSuggestionStrip(final SuggestedWords suggestedWords, - final CharSequence typedWord) { + private void showSuggestionStrip(final SuggestedWords suggestedWords, final String typedWord) { if (suggestedWords.isEmpty()) { clearSuggestionStrip(); return; } - final CharSequence autoCorrection; + final String autoCorrection; if (suggestedWords.mWillAutoCorrect) { autoCorrection = suggestedWords.getWord(1); } else { @@ -1989,9 +1988,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction if (mHandler.hasPendingUpdateSuggestions()) { updateSuggestionStrip(); } - final CharSequence typedAutoCorrection = mWordComposer.getAutoCorrectionOrNull(); + final String typedAutoCorrection = mWordComposer.getAutoCorrectionOrNull(); final String typedWord = mWordComposer.getTypedWord(); - final CharSequence autoCorrection = (typedAutoCorrection != null) + final String autoCorrection = (typedAutoCorrection != null) ? typedAutoCorrection : typedWord; if (autoCorrection != null) { if (TextUtils.isEmpty(typedWord)) { @@ -2022,7 +2021,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // Called from {@link SuggestionStripView} through the {@link SuggestionStripView#Listener} // interface @Override - public void pickSuggestionManually(final int index, final CharSequence suggestion) { + public void pickSuggestionManually(final int index, final String suggestion) { final SuggestedWords suggestedWords = mSuggestionStripView.getSuggestions(); // If this is a punctuation picked from the suggestion strip, pass it to onCodeInput if (suggestion.length() == 1 && isShowingPunctuationList()) { @@ -2107,13 +2106,13 @@ public final class LatinIME extends InputMethodService implements KeyboardAction /** * Commits the chosen word to the text field and saves it for later retrieval. */ - private void commitChosenWord(final CharSequence chosenWord, final int commitType, + private void commitChosenWord(final String chosenWord, final int commitType, final String separatorString) { final SuggestedWords suggestedWords = mSuggestionStripView.getSuggestions(); mConnection.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan( this, chosenWord, suggestedWords, mIsMainDictionaryAvailable), 1); // Add the word to the user history dictionary - final CharSequence prevWord = addToUserHistoryDictionary(chosenWord); + final String prevWord = addToUserHistoryDictionary(chosenWord); // TODO: figure out here if this is an auto-correct or if the best word is actually // what user typed. Note: currently this is done much later in // LastComposedWord#didCommitTypedWord by string equality of the remembered @@ -2132,7 +2131,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction setSuggestionStripShown(isSuggestionsStripVisible()); } - private CharSequence addToUserHistoryDictionary(final CharSequence suggestion) { + private String addToUserHistoryDictionary(final String suggestion) { if (TextUtils.isEmpty(suggestion)) return null; if (mSuggest == null) return null; @@ -2147,19 +2146,18 @@ public final class LatinIME extends InputMethodService implements KeyboardAction = mConnection.getNthPreviousWord(mCurrentSettings.mWordSeparators, 2); final String secondWord; if (mWordComposer.wasAutoCapitalized() && !mWordComposer.isMostlyCaps()) { - secondWord = suggestion.toString().toLowerCase( - mSubtypeSwitcher.getCurrentSubtypeLocale()); + secondWord = suggestion.toLowerCase(mSubtypeSwitcher.getCurrentSubtypeLocale()); } else { - secondWord = suggestion.toString(); + secondWord = suggestion; } // We demote unrecognized words (frequency < 0, below) by specifying them as "invalid". // We don't add words with 0-frequency (assuming they would be profanity etc.). final int maxFreq = AutoCorrection.getMaxFrequency( mSuggest.getUnigramDictionaries(), suggestion); if (maxFreq == 0) return null; - userHistoryDictionary.addToUserHistory(null == prevWord ? null : prevWord.toString(), - secondWord, maxFreq > 0); - return prevWord; + final String prevWordString = (null == prevWord) ? null : prevWord.toString(); + userHistoryDictionary.addToUserHistory(prevWordString, secondWord, maxFreq > 0); + return prevWordString; } return null; } @@ -2184,9 +2182,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction } private void revertCommit() { - final CharSequence previousWord = mLastComposedWord.mPrevWord; + final String previousWord = mLastComposedWord.mPrevWord; final String originallyTypedWord = mLastComposedWord.mTypedWord; - final CharSequence committedWord = mLastComposedWord.mCommittedWord; + final String committedWord = mLastComposedWord.mCommittedWord; final int cancelLength = committedWord.length(); final int separatorLength = LastComposedWord.getSeparatorLength( mLastComposedWord.mSeparatorString); @@ -2196,9 +2194,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction if (mWordComposer.isComposingWord()) { throw new RuntimeException("revertCommit, but we are composing a word"); } - final String wordBeforeCursor = + final CharSequence wordBeforeCursor = mConnection.getTextBeforeCursor(deleteLength, 0) - .subSequence(0, cancelLength).toString(); + .subSequence(0, cancelLength); if (!TextUtils.equals(committedWord, wordBeforeCursor)) { throw new RuntimeException("revertCommit check failed: we thought we were " + "reverting \"" + committedWord diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index 21441369e..bf2dfbc0b 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -398,7 +398,7 @@ public final class RichInputConnection { if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); } - public CharSequence getNthPreviousWord(final String sentenceSeperators, final int n) { + public String getNthPreviousWord(final String sentenceSeperators, final int n) { mIC = mParent.getCurrentInputConnection(); if (null == mIC) return null; final CharSequence prev = mIC.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); @@ -466,19 +466,22 @@ public final class RichInputConnection { // (n = 2) "abc|" -> null // (n = 2) "abc |" -> null // (n = 2) "abc. def|" -> null - public static CharSequence getNthPreviousWord(final CharSequence prev, + public static String getNthPreviousWord(final CharSequence prev, final String sentenceSeperators, final int n) { if (prev == null) return null; - String[] w = spaceRegex.split(prev); + final String[] w = spaceRegex.split(prev); // If we can't find n words, or we found an empty word, return null. - if (w.length < n || w[w.length - n].length() <= 0) return null; + if (w.length < n) return null; + final String nthPrevWord = w[w.length - n]; + final int length = nthPrevWord.length(); + if (length <= 0) return null; // If ends in a separator, return null - char lastChar = w[w.length - n].charAt(w[w.length - n].length() - 1); + final char lastChar = nthPrevWord.charAt(length - 1); if (sentenceSeperators.contains(String.valueOf(lastChar))) return null; - return w[w.length - n]; + return nthPrevWord; } /** @@ -511,19 +514,20 @@ public final class RichInputConnection { * be included in the returned range * @return a range containing the text surrounding the cursor */ - public Range getWordRangeAtCursor(String sep, int additionalPrecedingWordsCount) { + public Range getWordRangeAtCursor(final String sep, final int additionalPrecedingWordsCount) { mIC = mParent.getCurrentInputConnection(); if (mIC == null || sep == null) { return null; } - CharSequence before = mIC.getTextBeforeCursor(1000, 0); - CharSequence after = mIC.getTextAfterCursor(1000, 0); + final CharSequence before = mIC.getTextBeforeCursor(1000, 0); + final CharSequence after = mIC.getTextAfterCursor(1000, 0); if (before == null || after == null) { return null; } // Going backward, alternate skipping non-separators and separators until enough words // have been read. + int count = additionalPrecedingWordsCount; int start = before.length(); boolean isStoppingAtWhitespace = true; // toggles to indicate what to stop at while (true) { // see comments below for why this is guaranteed to halt @@ -540,7 +544,7 @@ public final class RichInputConnection { // isStoppingAtWhitespace is true every other time through the loop, // so additionalPrecedingWordsCount is guaranteed to become < 0, which // guarantees outer loop termination - if (isStoppingAtWhitespace && (--additionalPrecedingWordsCount < 0)) { + if (isStoppingAtWhitespace && (--count < 0)) { break; // outer loop } isStoppingAtWhitespace = !isStoppingAtWhitespace; @@ -558,7 +562,7 @@ public final class RichInputConnection { } } - int cursor = getCursorPosition(); + final int cursor = getCursorPosition(); if (start >= 0 && cursor + end <= after.length() + before.length()) { String word = before.toString().substring(start, before.length()) + after.toString().substring(0, end); @@ -569,8 +573,8 @@ public final class RichInputConnection { } public boolean isCursorTouchingWord(final SettingsValues settingsValues) { - CharSequence before = getTextBeforeCursor(1, 0); - CharSequence after = getTextAfterCursor(1, 0); + final CharSequence before = getTextBeforeCursor(1, 0); + final CharSequence after = getTextAfterCursor(1, 0); if (!TextUtils.isEmpty(before) && !settingsValues.isWordSeparator(before.charAt(0)) && !settingsValues.isSymbolExcludedFromWordSeparators(before.charAt(0))) { return true; diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java index df7709892..44b75b568 100644 --- a/java/src/com/android/inputmethod/latin/StringUtils.java +++ b/java/src/com/android/inputmethod/latin/StringUtils.java @@ -16,9 +16,11 @@ package com.android.inputmethod.latin; +import android.text.InputType; import android.text.TextUtils; -import com.android.inputmethod.keyboard.Keyboard; // For character constants +//For character constants +import com.android.inputmethod.keyboard.Keyboard; import java.util.ArrayList; import java.util.Locale; @@ -28,30 +30,30 @@ public final class StringUtils { // This utility class is not publicly instantiable. } - public static int codePointCount(String text) { + public static int codePointCount(final String text) { if (TextUtils.isEmpty(text)) return 0; return text.codePointCount(0, text.length()); } - public static boolean containsInArray(String key, String[] array) { + public static boolean containsInArray(final String key, final String[] array) { for (final String element : array) { if (key.equals(element)) return true; } return false; } - public static boolean containsInCsv(String key, String csv) { + public static boolean containsInCsv(final String key, final String csv) { if (TextUtils.isEmpty(csv)) return false; return containsInArray(key, csv.split(",")); } - public static String appendToCsvIfNotExists(String key, String csv) { + public static String appendToCsvIfNotExists(final String key, final String csv) { if (TextUtils.isEmpty(csv)) return key; if (containsInCsv(key, csv)) return csv; return csv + "," + key; } - public static String removeFromCsvIfExists(String key, String csv) { + public static String removeFromCsvIfExists(final String key, final String csv) { if (TextUtils.isEmpty(csv)) return ""; final String[] elements = csv.split(","); if (!containsInArray(key, elements)) return csv; @@ -62,83 +64,21 @@ public final class StringUtils { return TextUtils.join(",", result); } - /** - * Returns true if a and b are equal ignoring the case of the character. - * @param a first character to check - * @param b second character to check - * @return {@code true} if a and b are equal, {@code false} otherwise. - */ - public static boolean equalsIgnoreCase(char a, char b) { - // Some language, such as Turkish, need testing both cases. - return a == b - || Character.toLowerCase(a) == Character.toLowerCase(b) - || Character.toUpperCase(a) == Character.toUpperCase(b); - } - - /** - * Returns true if a and b are equal ignoring the case of the characters, including if they are - * both null. - * @param a first CharSequence to check - * @param b second CharSequence to check - * @return {@code true} if a and b are equal, {@code false} otherwise. - */ - public static boolean equalsIgnoreCase(CharSequence a, CharSequence b) { - if (a == b) - return true; // including both a and b are null. - if (a == null || b == null) - return false; - final int length = a.length(); - if (length != b.length()) - return false; - for (int i = 0; i < length; i++) { - if (!equalsIgnoreCase(a.charAt(i), b.charAt(i))) - return false; - } - return true; - } - - /** - * Returns true if a and b are equal ignoring the case of the characters, including if a is null - * and b is zero length. - * @param a CharSequence to check - * @param b character array to check - * @param offset start offset of array b - * @param length length of characters in array b - * @return {@code true} if a and b are equal, {@code false} otherwise. - * @throws IndexOutOfBoundsException - * if {@code offset < 0 || length < 0 || offset + length > data.length}. - * @throws NullPointerException if {@code b == null}. - */ - public static boolean equalsIgnoreCase(CharSequence a, char[] b, int offset, int length) { - if (offset < 0 || length < 0 || length > b.length - offset) - throw new IndexOutOfBoundsException("array.length=" + b.length + " offset=" + offset - + " length=" + length); - if (a == null) - return length == 0; // including a is null and b is zero length. - if (a.length() != length) - return false; - for (int i = 0; i < length; i++) { - if (!equalsIgnoreCase(a.charAt(i), b[offset + i])) - return false; - } - return true; - } - /** * Remove duplicates from an array of strings. * * This method will always keep the first occurrence of all strings at their position * in the array, removing the subsequent ones. */ - public static void removeDupes(final ArrayList suggestions) { + public static void removeDupes(final ArrayList suggestions) { if (suggestions.size() < 2) return; int i = 1; // Don't cache suggestions.size(), since we may be removing items while (i < suggestions.size()) { - final CharSequence cur = suggestions.get(i); + final String cur = suggestions.get(i); // Compare each suggestion with each previous suggestion for (int j = 0; j < i; j++) { - CharSequence previous = suggestions.get(j); + final String previous = suggestions.get(j); if (TextUtils.equals(cur, previous)) { suggestions.remove(i); i--; @@ -149,7 +89,7 @@ public final class StringUtils { } } - public static String toTitleCase(String s, Locale locale) { + public static String toTitleCase(final String s, final Locale locale) { if (s.length() <= 1) { // TODO: is this really correct? Shouldn't this be s.toUpperCase()? return s; @@ -165,21 +105,19 @@ public final class StringUtils { return s.toUpperCase(locale).charAt(0) + s.substring(1); } + private static final int[] EMPTY_CODEPOINTS = {}; + public static int[] toCodePointArray(final String string) { - final char[] characters = string.toCharArray(); - final int length = characters.length; - final int[] codePoints = new int[Character.codePointCount(characters, 0, length)]; + final int length = string.length(); if (length <= 0) { - return new int[0]; + return EMPTY_CODEPOINTS; } - int codePoint = Character.codePointAt(characters, 0); - int dsti = 0; - for (int srci = Character.charCount(codePoint); - srci < length; srci += Character.charCount(codePoint), ++dsti) { - codePoints[dsti] = codePoint; - codePoint = Character.codePointAt(characters, srci); + final int[] codePoints = new int[string.codePointCount(0, length)]; + int destIndex = 0; + for (int index = 0; index < length; index = string.offsetByCodePoints(index, 1)) { + codePoints[destIndex] = string.codePointAt(index); + destIndex++; } - codePoints[dsti] = codePoint; return codePoints; } diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index f0e3b4ebd..7e03cdb9c 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -38,7 +38,7 @@ public final class Suggest { public static final String TAG = Suggest.class.getSimpleName(); // Session id for - // {@link #getSuggestedWords(WordComposer,CharSequence,ProximityInfo,boolean,int)}. + // {@link #getSuggestedWords(WordComposer,String,ProximityInfo,boolean,int)}. public static final int SESSION_TYPING = 0; public static final int SESSION_GESTURE = 1; @@ -138,7 +138,7 @@ public final class Suggest { * Sets an optional user dictionary resource to be loaded. The user dictionary is consulted * before the main dictionary, if set. This refers to the system-managed user dictionary. */ - public void setUserDictionary(UserBinaryDictionary userDictionary) { + public void setUserDictionary(final UserBinaryDictionary userDictionary) { addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_USER, userDictionary); } @@ -147,12 +147,12 @@ public final class Suggest { * the contacts dictionary by passing null to this method. In this case no contacts dictionary * won't be used. */ - public void setContactsDictionary(ContactsBinaryDictionary contactsDictionary) { + public void setContactsDictionary(final ContactsBinaryDictionary contactsDictionary) { mContactsDict = contactsDictionary; addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_CONTACTS, contactsDictionary); } - public void setUserHistoryDictionary(UserHistoryDictionary userHistoryDictionary) { + public void setUserHistoryDictionary(final UserHistoryDictionary userHistoryDictionary) { addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_USER_HISTORY, userHistoryDictionary); } @@ -160,9 +160,9 @@ public final class Suggest { mAutoCorrectionThreshold = threshold; } - public SuggestedWords getSuggestedWords( - final WordComposer wordComposer, CharSequence prevWordForBigram, - final ProximityInfo proximityInfo, final boolean isCorrectionEnabled, int sessionId) { + public SuggestedWords getSuggestedWords(final WordComposer wordComposer, + final String prevWordForBigram, final ProximityInfo proximityInfo, + final boolean isCorrectionEnabled, final int sessionId) { LatinImeLogger.onStartSuggestion(prevWordForBigram); if (wordComposer.isBatchMode()) { return getSuggestedWordsForBatchInput( @@ -174,9 +174,9 @@ public final class Suggest { } // Retrieves suggestions for the typing input. - private SuggestedWords getSuggestedWordsForTypingInput( - final WordComposer wordComposer, CharSequence prevWordForBigram, - final ProximityInfo proximityInfo, final boolean isCorrectionEnabled) { + private SuggestedWords getSuggestedWordsForTypingInput(final WordComposer wordComposer, + final String prevWordForBigram, final ProximityInfo proximityInfo, + final boolean isCorrectionEnabled) { final int trailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount(); final BoundedTreeSet suggestionsSet = new BoundedTreeSet(sSuggestedWordInfoComparator, MAX_SUGGESTIONS); @@ -203,7 +203,7 @@ public final class Suggest { wordComposerForLookup, prevWordForBigram, proximityInfo)); } - final CharSequence whitelistedWord; + final String whitelistedWord; if (suggestionsSet.isEmpty()) { whitelistedWord = null; } else if (SuggestedWordInfo.KIND_WHITELIST != suggestionsSet.first().mKind) { @@ -287,9 +287,9 @@ public final class Suggest { } // Retrieves suggestions for the batch input. - private SuggestedWords getSuggestedWordsForBatchInput( - final WordComposer wordComposer, CharSequence prevWordForBigram, - final ProximityInfo proximityInfo, int sessionId) { + private SuggestedWords getSuggestedWordsForBatchInput(final WordComposer wordComposer, + final String prevWordForBigram, final ProximityInfo proximityInfo, + final int sessionId) { final BoundedTreeSet suggestionsSet = new BoundedTreeSet(sSuggestedWordInfoComparator, MAX_SUGGESTIONS); @@ -307,7 +307,7 @@ public final class Suggest { } for (SuggestedWordInfo wordInfo : suggestionsSet) { - LatinImeLogger.onAddSuggestedWord(wordInfo.mWord.toString(), wordInfo.mSourceDict); + LatinImeLogger.onAddSuggestedWord(wordInfo.mWord, wordInfo.mSourceDict); } final ArrayList suggestionsContainer = @@ -372,7 +372,7 @@ public final class Suggest { if (o1.mScore < o2.mScore) return 1; if (o1.mCodePointCount < o2.mCodePointCount) return -1; if (o1.mCodePointCount > o2.mCodePointCount) return 1; - return o1.mWord.toString().compareTo(o2.mWord.toString()); + return o1.mWord.compareTo(o2.mWord); } } private static final SuggestedWordInfoComparator sSuggestedWordInfoComparator = @@ -383,16 +383,17 @@ public final class Suggest { final boolean isFirstCharCapitalized, final int trailingSingleQuotesCount) { final StringBuilder sb = new StringBuilder(wordInfo.mWord.length()); if (isAllUpperCase) { - sb.append(wordInfo.mWord.toString().toUpperCase(locale)); + sb.append(wordInfo.mWord.toUpperCase(locale)); } else if (isFirstCharCapitalized) { - sb.append(StringUtils.toTitleCase(wordInfo.mWord.toString(), locale)); + sb.append(StringUtils.toTitleCase(wordInfo.mWord, locale)); } else { sb.append(wordInfo.mWord); } for (int i = trailingSingleQuotesCount - 1; i >= 0; --i) { sb.appendCodePoint(Keyboard.CODE_SINGLE_QUOTE); } - return new SuggestedWordInfo(sb, wordInfo.mScore, wordInfo.mKind, wordInfo.mSourceDict); + return new SuggestedWordInfo(sb.toString(), wordInfo.mScore, wordInfo.mKind, + wordInfo.mSourceDict); } public void close() { diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index ad94affb2..572f2906e 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -90,11 +90,14 @@ public final class SuggestedWords { public static ArrayList getFromApplicationSpecifiedCompletions( final CompletionInfo[] infos) { final ArrayList result = CollectionUtils.newArrayList(); - for (CompletionInfo info : infos) { - if (null != info && info.getText() != null) { - result.add(new SuggestedWordInfo(info.getText(), SuggestedWordInfo.MAX_SCORE, - SuggestedWordInfo.KIND_APP_DEFINED, Dictionary.TYPE_APPLICATION_DEFINED)); - } + for (final CompletionInfo info : infos) { + if (info == null) continue; + final CharSequence text = info.getText(); + if (null == text) continue; + final SuggestedWordInfo suggestedWordInfo = new SuggestedWordInfo(text.toString(), + SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_APP_DEFINED, + Dictionary.TYPE_APPLICATION_DEFINED); + result.add(suggestedWordInfo); } return result; } @@ -102,7 +105,7 @@ public final class SuggestedWords { // Should get rid of the first one (what the user typed previously) from suggestions // and replace it with what the user currently typed. public static ArrayList getTypedWordAndPreviousSuggestions( - final CharSequence typedWord, final SuggestedWords previousSuggestions) { + final String typedWord, final SuggestedWords previousSuggestions) { final ArrayList suggestionsList = CollectionUtils.newArrayList(); final HashSet alreadySeen = CollectionUtils.newHashSet(); suggestionsList.add(new SuggestedWordInfo(typedWord, SuggestedWordInfo.MAX_SCORE, @@ -111,7 +114,7 @@ public final class SuggestedWords { final int previousSize = previousSuggestions.size(); for (int pos = 1; pos < previousSize; pos++) { final SuggestedWordInfo prevWordInfo = previousSuggestions.getWordInfo(pos); - final String prevWord = prevWordInfo.mWord.toString(); + final String prevWord = prevWordInfo.mWord; // Filter out duplicate suggestion. if (!alreadySeen.contains(prevWord)) { suggestionsList.add(prevWordInfo); @@ -139,9 +142,9 @@ public final class SuggestedWords { public final String mSourceDict; private String mDebugString = ""; - public SuggestedWordInfo(final CharSequence word, final int score, final int kind, + public SuggestedWordInfo(final String word, final int score, final int kind, final String sourceDict) { - mWord = word.toString(); + mWord = word; mScore = score; mKind = kind; mSourceDict = sourceDict; @@ -149,7 +152,7 @@ public final class SuggestedWords { } - public void setDebugString(String str) { + public void setDebugString(final String str) { if (null == str) throw new NullPointerException("Debug info is null"); mDebugString = str; } @@ -171,7 +174,7 @@ public final class SuggestedWords { if (TextUtils.isEmpty(mDebugString)) { return mWord; } else { - return mWord + " (" + mDebugString.toString() + ")"; + return mWord + " (" + mDebugString + ")"; } } diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java index 8f21b7b4a..ec4dc1436 100644 --- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java @@ -33,13 +33,13 @@ public final class SynchronouslyLoadedContactsBinaryDictionary extends ContactsB @Override public synchronized ArrayList getSuggestions(final WordComposer codes, - final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) { + final String prevWordForBigrams, final ProximityInfo proximityInfo) { syncReloadDictionaryIfRequired(); return super.getSuggestions(codes, prevWordForBigrams, proximityInfo); } @Override - public synchronized boolean isValidWord(CharSequence word) { + public synchronized boolean isValidWord(final String word) { syncReloadDictionaryIfRequired(); return isValidWordInner(word); } diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java index 612f54d73..4bdaf2039 100644 --- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java @@ -36,13 +36,13 @@ public final class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDic @Override public synchronized ArrayList getSuggestions(final WordComposer codes, - final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) { + final String prevWordForBigrams, final ProximityInfo proximityInfo) { syncReloadDictionaryIfRequired(); return super.getSuggestions(codes, prevWordForBigrams, proximityInfo); } @Override - public synchronized boolean isValidWord(CharSequence word) { + public synchronized boolean isValidWord(final String word) { syncReloadDictionaryIfRequired(); return isValidWordInner(word); } diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java index 60e6fa127..00c3cbe0a 100644 --- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java @@ -200,7 +200,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { mContext.startActivity(intent); } - private void addWords(Cursor cursor) { + private void addWords(final Cursor cursor) { // 16 is JellyBean, but we want this to compile against ICS. final boolean hasShortcutColumn = android.os.Build.VERSION.SDK_INT >= 16; clearFusionDictionary(); diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java index 3615fa1fb..a80a64267 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java @@ -122,7 +122,7 @@ public final class UserHistoryDictionary extends ExpandableDictionary { @Override protected ArrayList getWordsInner(final WordComposer composer, - final CharSequence prevWord, final ProximityInfo proximityInfo) { + final String prevWord, final ProximityInfo proximityInfo) { // Inhibit suggestions (not predictions) for user history for now. Removing this method // is enough to use it through the standard ExpandableDictionary way. return null; @@ -132,7 +132,7 @@ public final class UserHistoryDictionary extends ExpandableDictionary { * Return whether the passed charsequence is in the dictionary. */ @Override - public synchronized boolean isValidWord(final CharSequence word) { + public synchronized boolean isValidWord(final String word) { // TODO: figure out what is the correct thing to do here. return false; } @@ -145,7 +145,7 @@ public final class UserHistoryDictionary extends ExpandableDictionary { * context, as in beginning of a sentence for example. * The second word may not be null (a NullPointerException would be thrown). */ - public int addToUserHistory(final String word1, String word2, boolean isValid) { + public int addToUserHistory(final String word1, final String word2, final boolean isValid) { if (word2.length() >= BinaryDictionary.MAX_WORD_LENGTH || (word1 != null && word1.length() >= BinaryDictionary.MAX_WORD_LENGTH)) { return -1; @@ -175,7 +175,7 @@ public final class UserHistoryDictionary extends ExpandableDictionary { return -1; } - public boolean cancelAddingUserHistory(String word1, String word2) { + public boolean cancelAddingUserHistory(final String word1, final String word2) { if (mBigramListLock.tryLock()) { try { if (mBigramList.removeBigram(word1, word2)) { @@ -226,7 +226,8 @@ public final class UserHistoryDictionary extends ExpandableDictionary { final ExpandableDictionary dictionary = this; final OnAddWordListener listener = new OnAddWordListener() { @Override - public void setUnigram(String word, String shortcutTarget, int frequency) { + public void setUnigram(final String word, final String shortcutTarget, + final int frequency) { profTotal++; if (DBG_SAVE_RESTORE) { Log.d(TAG, "load unigram: " + word + "," + frequency); @@ -236,7 +237,7 @@ public final class UserHistoryDictionary extends ExpandableDictionary { } @Override - public void setBigram(String word1, String word2, int frequency) { + public void setBigram(final String word1, final String word2, final int frequency) { if (word1.length() < BinaryDictionary.MAX_WORD_LENGTH && word2.length() < BinaryDictionary.MAX_WORD_LENGTH) { profTotal++; @@ -250,7 +251,7 @@ public final class UserHistoryDictionary extends ExpandableDictionary { mBigramList.addBigram(word1, word2, (byte)frequency); } }; - + // Load the dictionary from binary file FileInputStream inStream = null; try { @@ -292,8 +293,9 @@ public final class UserHistoryDictionary extends ExpandableDictionary { private final SharedPreferences mPrefs; private final Context mContext; - public UpdateBinaryTask(UserHistoryDictionaryBigramList pendingWrites, String locale, - UserHistoryDictionary dict, SharedPreferences prefs, Context context) { + public UpdateBinaryTask(final UserHistoryDictionaryBigramList pendingWrites, + final String locale, final UserHistoryDictionary dict, + final SharedPreferences prefs, final Context context) { mBigramList = pendingWrites; mLocale = locale; mUserHistoryDictionary = dict; @@ -303,7 +305,7 @@ public final class UserHistoryDictionary extends ExpandableDictionary { } @Override - protected Void doInBackground(Void... v) { + protected Void doInBackground(final Void... v) { if (mUserHistoryDictionary.isTest) { // If isTest == true, wait until the lock is released. mUserHistoryDictionary.mBigramListLock.lock(); @@ -360,7 +362,7 @@ public final class UserHistoryDictionary extends ExpandableDictionary { } @Override - public int getFrequency(String word1, String word2) { + public int getFrequency(final String word1, final String word2) { final int freq; if (word1 == null) { // unigram freq = FREQUENCY_FOR_TYPED; diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index da0071adc..229aa8a48 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -38,7 +38,7 @@ public final class WordComposer { private int[] mPrimaryKeyCodes; private final InputPointers mInputPointers = new InputPointers(N); private final StringBuilder mTypedWord; - private CharSequence mAutoCorrection; + private String mAutoCorrection; private boolean mIsResumed; private boolean mIsBatchMode; @@ -64,7 +64,7 @@ public final class WordComposer { refreshSize(); } - public WordComposer(WordComposer source) { + public WordComposer(final WordComposer source) { mPrimaryKeyCodes = Arrays.copyOf(source.mPrimaryKeyCodes, source.mPrimaryKeyCodes.length); mTypedWord = new StringBuilder(source.mTypedWord); mInputPointers.copy(source.mInputPointers); @@ -121,7 +121,8 @@ public final class WordComposer { return mInputPointers; } - private static boolean isFirstCharCapitalized(int index, int codePoint, boolean previous) { + private static boolean isFirstCharCapitalized(final int index, final int codePoint, + final boolean previous) { if (index == 0) return Character.isUpperCase(codePoint); return previous && !Character.isUpperCase(codePoint); } @@ -129,7 +130,7 @@ public final class WordComposer { /** * Add a new keystroke, with the pressed key's code point with the touch point coordinates. */ - public void add(int primaryCode, int keyX, int keyY) { + public void add(final int primaryCode, final int keyX, final int keyY) { final int newIndex = size(); mTypedWord.appendCodePoint(primaryCode); refreshSize(); @@ -156,12 +157,12 @@ public final class WordComposer { mAutoCorrection = null; } - public void setBatchInputPointers(InputPointers batchPointers) { + public void setBatchInputPointers(final InputPointers batchPointers) { mInputPointers.set(batchPointers); mIsBatchMode = true; } - public void setBatchInputWord(CharSequence word) { + public void setBatchInputWord(final String word) { reset(); mIsBatchMode = true; final int length = word.length(); @@ -321,14 +322,14 @@ public final class WordComposer { /** * Sets the auto-correction for this word. */ - public void setAutoCorrection(final CharSequence correction) { + public void setAutoCorrection(final String correction) { mAutoCorrection = correction; } /** * @return the auto-correction for this word, or null if none. */ - public CharSequence getAutoCorrectionOrNull() { + public String getAutoCorrectionOrNull() { return mAutoCorrection; } @@ -341,7 +342,7 @@ public final class WordComposer { // `type' should be one of the LastComposedWord.COMMIT_TYPE_* constants above. public LastComposedWord commitWord(final int type, final String committedWord, - final String separatorString, final CharSequence prevWord) { + final String separatorString, final String prevWord) { // Note: currently, we come here whenever we commit a word. If it's a MANUAL_PICK // or a DECIDED_WORD we may cancel the commit later; otherwise, we should deactivate // the last composed word to ensure this does not happen. diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 5a11ae534..49b98863f 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -212,7 +212,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService } } - private final ArrayList mSuggestions; + private final ArrayList mSuggestions; private final int[] mScores; private final String mOriginalText; private final float mSuggestionThreshold; @@ -335,7 +335,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService gatheredSuggestions = mSuggestions.toArray(EMPTY_STRING_ARRAY); final int bestScore = mScores[mLength - 1]; - final CharSequence bestSuggestion = mSuggestions.get(0); + final String bestSuggestion = mSuggestions.get(0); final float normalizedScore = BinaryDictionary.calcNormalizedScore( mOriginalText, bestSuggestion.toString(), bestScore); diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java index 53ed4d3c3..a8f323999 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java @@ -268,7 +268,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { dictInfo.mDictionary.getSuggestions(composer, prevWord, dictInfo.mProximityInfo); for (final SuggestedWordInfo suggestion : suggestions) { - final String suggestionStr = suggestion.mWord.toString(); + final String suggestionStr = suggestion.mWord; suggestionsGatherer.addWord(suggestionStr.toCharArray(), null, 0, suggestionStr.length(), suggestion.mScore); } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java index 1fb2bbb6a..eae5d2e60 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java @@ -51,11 +51,11 @@ public final class DictionaryPool extends LinkedBlockingQueue new Dictionary(Dictionary.TYPE_MAIN) { @Override public ArrayList getSuggestions(final WordComposer composer, - final CharSequence prevWord, final ProximityInfo proximityInfo) { + final String prevWord, final ProximityInfo proximityInfo) { return noSuggestions; } @Override - public boolean isValidWord(CharSequence word) { + public boolean isValidWord(final String word) { // This is never called. However if for some strange reason it ever gets // called, returning true is less destructive (it will not underline the // word in red). diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java index 42626951d..35d5a0067 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java @@ -65,7 +65,7 @@ public final class MoreSuggestions extends Keyboard { int pos = fromPos, rowStartPos = fromPos; final int size = Math.min(suggestions.size(), SuggestionStripView.MAX_SUGGESTIONS); while (pos < size) { - final String word = suggestions.getWord(pos).toString(); + final String word = suggestions.getWord(pos); // TODO: Should take care of text x-scaling. mWidths[pos] = (int)view.getLabelWidth(word, paint) + padding; final int numColumn = pos - rowStartPos + 1; diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index 3cf5857fc..e7cb97fc2 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -77,7 +77,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick OnLongClickListener { public interface Listener { public boolean addWordToUserDictionary(String word); - public void pickSuggestionManually(int index, CharSequence word); + public void pickSuggestionManually(int index, String word); } // The maximum number of suggestions available. See {@link Suggest#mPrefMaxSuggestions}. @@ -286,7 +286,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick private CharSequence getStyledSuggestionWord(final SuggestedWords suggestedWords, final int pos) { - final CharSequence word = suggestedWords.getWord(pos); + final String word = suggestedWords.getWord(pos); final boolean isAutoCorrect = pos == 1 && suggestedWords.willAutoCorrect(); final boolean isTypedWordValid = pos == 0 && suggestedWords.mTypedWordValid; if (!isAutoCorrect && !isTypedWordValid) @@ -338,7 +338,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick // is in slot 1. if (index == mCenterSuggestionIndex && AutoCorrection.shouldBlockAutoCorrectionBySafetyNet( - suggestedWords.getWord(1).toString(), suggestedWords.getWord(0))) { + suggestedWords.getWord(1), suggestedWords.getWord(0))) { return 0xFFFF0000; } } @@ -409,7 +409,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick x += word.getMeasuredWidth(); if (DBG && pos < suggestedWords.size()) { - final CharSequence debugInfo = Utils.getDebugInfo(suggestedWords, pos); + final String debugInfo = Utils.getDebugInfo(suggestedWords, pos); if (debugInfo != null) { final TextView info = mInfos.get(pos); info.setText(debugInfo); @@ -466,7 +466,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick final TextView word = mWords.get(index); word.setEnabled(true); word.setTextColor(mColorAutoCorrect); - final CharSequence text = suggestedWords.getWord(index); + final String text = suggestedWords.getWord(index); word.setText(text); word.setTextScaleX(1.0f); word.setCompoundDrawables(null, null, null, null); @@ -476,7 +476,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick mMoreSuggestionsAvailable = false; } - public void layoutAddToDictionaryHint(final CharSequence word, final ViewGroup stripView, + public void layoutAddToDictionaryHint(final String word, final ViewGroup stripView, final int stripWidth, final CharSequence hintText, final OnClickListener listener) { final int width = stripWidth - mDividerWidth - mPadding * 2; @@ -690,7 +690,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick && mParams.isAddToDictionaryShowing(mSuggestionsStrip.getChildAt(0)); } - public void showAddToDictionaryHint(final CharSequence word, final CharSequence hintText) { + public void showAddToDictionaryHint(final String word, final CharSequence hintText) { clear(); mParams.layoutAddToDictionaryHint(word, mSuggestionsStrip, getWidth(), hintText, this); } @@ -723,7 +723,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick @Override public boolean onCustomRequest(final int requestCode) { final int index = requestCode; - final CharSequence word = mSuggestedWords.getWord(index); + final String word = mSuggestedWords.getWord(index); mListener.pickSuggestionManually(index, word); dismissMoreSuggestions(); return true; @@ -871,7 +871,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick if (index >= mSuggestedWords.size()) return; - final CharSequence word = mSuggestedWords.getWord(index); + final String word = mSuggestedWords.getWord(index); mListener.pickSuggestionManually(index, word); } diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java index eb5002059..70330509f 100644 --- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java +++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java @@ -281,7 +281,7 @@ public class InputTestsBase extends ServiceTestCase { waitForDictionaryToBeLoaded(); } - protected void pickSuggestionManually(final int index, final CharSequence suggestion) { + protected void pickSuggestionManually(final int index, final String suggestion) { mLatinIME.pickSuggestionManually(index, suggestion); } -- cgit v1.2.3-83-g751a From 15f6d4ae34664ea3d92827a2c3003198c0bac70b Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Wed, 3 Oct 2012 17:36:45 +0900 Subject: Add @UsedForTesting and @ExternallyReferenced annotations Bug: 7268357 Change-Id: I0b7e0c19f04af9ae30874d0a4c26ad81bc80be8c --- java/proguard.flags | 69 +++------------------- .../annotations/ExternallyReferenced.java | 24 ++++++++ .../inputmethod/annotations/UsedForTesting.java | 24 ++++++++ .../inputmethod/keyboard/KeyboardLayoutSet.java | 3 +- .../inputmethod/keyboard/MainKeyboardView.java | 6 +- .../inputmethod/keyboard/MoreKeysKeyboard.java | 3 +- .../keyboard/internal/KeyboardBuilder.java | 3 +- .../keyboard/internal/KeyboardTextsSet.java | 3 +- .../keyboard/internal/TouchPositionCorrection.java | 3 +- .../inputmethod/latin/BinaryDictionary.java | 3 +- .../inputmethod/latin/ExpandableDictionary.java | 22 +------ .../android/inputmethod/latin/InputPointers.java | 8 ++- .../com/android/inputmethod/latin/LatinIME.java | 11 ++-- .../src/com/android/inputmethod/latin/Suggest.java | 4 +- .../inputmethod/latin/UserHistoryDictIOUtils.java | 7 ++- .../inputmethod/latin/UserHistoryDictionary.java | 4 +- .../latin/makedict/BinaryDictIOUtils.java | 6 ++ .../latin/makedict/BinaryDictInputOutput.java | 2 + .../spellcheck/SpellCheckerProximityInfo.java | 3 +- tools/dicttool/Android.mk | 6 +- .../latin/makedict/BinaryDictInputOutputTest.java | 14 +---- tools/dicttool/tests/etc/test-dicttool.sh | 2 +- .../keyboard/internal/KeyboardTextsSet.tmpl | 3 +- 23 files changed, 116 insertions(+), 117 deletions(-) create mode 100644 java/src/com/android/inputmethod/annotations/ExternallyReferenced.java create mode 100644 java/src/com/android/inputmethod/annotations/UsedForTesting.java (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/proguard.flags b/java/proguard.flags index ac5b7df16..d65924f7c 100644 --- a/java/proguard.flags +++ b/java/proguard.flags @@ -1,64 +1,11 @@ --keep class com.android.inputmethod.latin.BinaryDictionary { - int mDictLength; - (...); +# Keep classes and methods that have the @UsedForTesting annotation +-keep @com.android.inputmethod.annotations.UsedForTesting class * +-keepclassmembers class * { +@com.android.inputmethod.annotations.UsedForTesting *; } --keep class com.android.inputmethod.keyboard.ProximityInfo { - (com.android.inputmethod.keyboard.ProximityInfo); +# Keep classes and methods that have the @ExternallyReferenced annotation +-keep @com.android.inputmethod.annotations.ExternallyReferenced class * +-keepclassmembers class * { +@com.android.inputmethod.annotations.ExternallyReferenced *; } - --keep class com.android.inputmethod.latin.Suggest { - (...); - com.android.inputmethod.latin.SuggestedWords getSuggestions(...); -} - --keep class com.android.inputmethod.latin.AutoCorrection { - java.lang.CharSequence getAutoCorrectionWord(); -} - --keep class com.android.inputmethod.latin.Utils { - boolean equalsIgnoreCase(...); -} - --keep class com.android.inputmethod.latin.InputPointers { - *; -} - --keep class com.android.inputmethod.latin.ResizableIntArray { - *; -} - --keep class com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsFragment { - *; -} - --keep class com.android.inputmethod.keyboard.MainKeyboardView { - # Keep getter/setter methods for ObjectAnimator - int getLanguageOnSpacebarAnimAlpha(); - void setLanguageOnSpacebarAnimAlpha(int); - int getAltCodeKeyWhileTypingAnimAlpha(); - void setAltCodeKeyWhileTypingAnimAlpha(int); -} - --keep class com.android.inputmethod.keyboard.MoreKeysKeyboard$Builder$MoreKeysKeyboardParams { - (...); -} - --keepclasseswithmembernames class * { - native ; -} - --keep class com.android.inputmethod.research.ResearchLogger { - void flush(); - void publishCurrentLogUnit(...); -} - --keep class com.android.inputmethod.keyboard.KeyboardLayoutSet$Builder { - void setTouchPositionCorrectionEnabled(...); -} - -# The support library contains references to newer platform versions. -# Don't warn about those in case this app is linking against an older -# platform version. We know about them, and they are safe. --dontwarn android.support.v4.** --dontwarn android.support.v13.** diff --git a/java/src/com/android/inputmethod/annotations/ExternallyReferenced.java b/java/src/com/android/inputmethod/annotations/ExternallyReferenced.java new file mode 100644 index 000000000..ea5f12ce2 --- /dev/null +++ b/java/src/com/android/inputmethod/annotations/ExternallyReferenced.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.annotations; + +/** + * Denotes that the class, method or field should not be eliminated by ProGuard, + * because it is externally referenced. (See proguard.flags) + */ +public @interface ExternallyReferenced { +} diff --git a/java/src/com/android/inputmethod/annotations/UsedForTesting.java b/java/src/com/android/inputmethod/annotations/UsedForTesting.java new file mode 100644 index 000000000..2ada091e4 --- /dev/null +++ b/java/src/com/android/inputmethod/annotations/UsedForTesting.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.annotations; + +/** + * Denotes that the class, method or field should not be eliminated by ProGuard, + * so that unit tests can access it. (See proguard.flags) + */ +public @interface UsedForTesting { +} diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java index ee373e72f..4d5d7e14e 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java @@ -34,6 +34,7 @@ import android.util.Xml; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodSubtype; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.compat.EditorInfoCompatUtils; import com.android.inputmethod.keyboard.internal.KeyboardBuilder; import com.android.inputmethod.keyboard.internal.KeyboardParams; @@ -265,7 +266,7 @@ public final class KeyboardLayoutSet { return this; } - // For test only + @UsedForTesting public void disableTouchPositionCorrectionDataForTest() { mParams.mDisableTouchPositionCorrectionDataForTest = true; } diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index 3e6f92c2a..5b6820fa6 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -41,6 +41,7 @@ import android.widget.PopupWindow; import com.android.inputmethod.accessibility.AccessibilityUtils; import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; +import com.android.inputmethod.annotations.ExternallyReferenced; import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; import com.android.inputmethod.keyboard.internal.KeyDrawParams; @@ -417,20 +418,23 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack return animator; } - // Getter/setter methods for {@link ObjectAnimator}. + @ExternallyReferenced public int getLanguageOnSpacebarAnimAlpha() { return mLanguageOnSpacebarAnimAlpha; } + @ExternallyReferenced public void setLanguageOnSpacebarAnimAlpha(final int alpha) { mLanguageOnSpacebarAnimAlpha = alpha; invalidateKey(mSpaceKey); } + @ExternallyReferenced public int getAltCodeKeyWhileTypingAnimAlpha() { return mAltCodeKeyWhileTypingAnimAlpha; } + @ExternallyReferenced public void setAltCodeKeyWhileTypingAnimAlpha(final int alpha) { mAltCodeKeyWhileTypingAnimAlpha = alpha; updateAltCodeKeyWhileTyping(); diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java index d7d4be40b..3826a39a4 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java @@ -20,6 +20,7 @@ import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.view.View; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.keyboard.internal.KeyboardBuilder; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.internal.KeyboardParams; @@ -39,7 +40,7 @@ public final class MoreKeysKeyboard extends Keyboard { return mDefaultKeyCoordX; } - /* package for test */ + @UsedForTesting static class MoreKeysKeyboardParams extends KeyboardParams { public boolean mIsFixedOrder; /* package */int mTopRowAdjustment; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java index b314a3795..36342688e 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java @@ -27,6 +27,7 @@ import android.util.TypedValue; import android.util.Xml; import android.view.InflateException; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardId; @@ -177,7 +178,7 @@ public class KeyboardBuilder { return this; } - // For test only + @UsedForTesting public void disableTouchPositionCorrectionDataForTest() { mParams.mTouchPositionCorrection.setEnabled(false); } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java index 3b7c6ad7a..c3875acb5 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java @@ -19,6 +19,7 @@ package com.android.inputmethod.keyboard.internal; import android.content.Context; import android.content.res.Resources; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.CollectionUtils; import com.android.inputmethod.latin.R; @@ -64,7 +65,7 @@ public final class KeyboardTextsSet { loadStringResourcesInternal(context, RESOURCE_NAMES, R.string.english_ime_name); } - /* package for test */ + @UsedForTesting void loadStringResourcesInternal(Context context, final String[] resourceNames, int referenceId) { final Resources res = context.getResources(); diff --git a/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java b/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java index d8950a713..d7a2b6f39 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java +++ b/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java @@ -16,6 +16,7 @@ package com.android.inputmethod.keyboard.internal; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.LatinImeLogger; public final class TouchPositionCorrection { @@ -66,7 +67,7 @@ public final class TouchPositionCorrection { } } - // For test only + @UsedForTesting public void setEnabled(final boolean enabled) { mEnabled = enabled; } diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 9c48aa1a4..8c005f0e6 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -81,7 +81,6 @@ public final class BinaryDictionary extends Dictionary { /** * Constructor for the binary dictionary. This is supposed to be called from the * dictionary factory. - * All implementations should pass null into flagArray, except for testing purposes. * @param context the context to access the environment from. * @param filename the name of the file to read through native code. * @param offset the offset of the dictionary data within the file. @@ -174,7 +173,7 @@ public final class BinaryDictionary extends Dictionary { return suggestions; } - /* package for test */ boolean isValidDictionary() { + public boolean isValidDictionary() { return mNativeDict != 0; } diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java index 8cdc2a0af..fdd0250a3 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -267,8 +267,7 @@ public class ExpandableDictionary extends Dictionary { // This reloads the dictionary if required, and returns whether it's currently updating its // contents or not. - // @VisibleForTesting - boolean reloadDictionaryIfRequired() { + private boolean reloadDictionaryIfRequired() { synchronized (mUpdatingLock) { // If we need to update, start off a background task if (mRequiresReload) startDictionaryLoadingTaskLocked(); @@ -613,25 +612,6 @@ public class ExpandableDictionary extends Dictionary { } } - /** - * Used for testing purposes and in the spell checker - * This function will wait for loading from database to be done - */ - void waitForDictionaryLoading() { - while (mUpdatingDictionary) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - // - } - } - } - - protected final void blockingReloadDictionaryIfRequired() { - reloadDictionaryIfRequired(); - waitForDictionaryLoading(); - } - // Local to reverseLookUp, but do not allocate each time. private final char[] mLookedUpString = new char[BinaryDictionary.MAX_WORD_LENGTH]; diff --git a/java/src/com/android/inputmethod/latin/InputPointers.java b/java/src/com/android/inputmethod/latin/InputPointers.java index 6b48aabb3..7dffd96dd 100644 --- a/java/src/com/android/inputmethod/latin/InputPointers.java +++ b/java/src/com/android/inputmethod/latin/InputPointers.java @@ -16,6 +16,8 @@ package com.android.inputmethod.latin; +import com.android.inputmethod.annotations.UsedForTesting; + // TODO: This class is not thread-safe. public final class InputPointers { private final int mDefaultCapacity; @@ -39,7 +41,8 @@ public final class InputPointers { mTimes.add(index, time); } - public void addPointer(int x, int y, int pointerId, int time) { + @UsedForTesting + void addPointer(int x, int y, int pointerId, int time) { mXCoordinates.add(x); mYCoordinates.add(y); mPointerIds.add(pointerId); @@ -66,7 +69,8 @@ public final class InputPointers { * @param startPos the starting index of the pointers in {@code src}. * @param length the number of pointers to be appended. */ - public void append(InputPointers src, int startPos, int length) { + @UsedForTesting + void append(InputPointers src, int startPos, int length) { if (length == 0) { return; } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 4cf6a5112..869ce7286 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -60,6 +60,7 @@ import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.accessibility.AccessibilityUtils; import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.compat.CompatUtils; import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; import com.android.inputmethod.compat.InputMethodServiceCompatUtils; @@ -132,14 +133,14 @@ public final class LatinIME extends InputMethodService implements KeyboardAction private View mKeyPreviewBackingView; private View mSuggestionsContainer; private SuggestionStripView mSuggestionStripView; - /* package for tests */ Suggest mSuggest; + @UsedForTesting Suggest mSuggest; private CompletionInfo[] mApplicationSpecifiedCompletions; private ApplicationInfo mTargetApplicationInfo; private InputMethodManagerCompatWrapper mImm; private Resources mResources; private SharedPreferences mPrefs; - /* package for tests */ final KeyboardSwitcher mKeyboardSwitcher; + @UsedForTesting final KeyboardSwitcher mKeyboardSwitcher; private final SubtypeSwitcher mSubtypeSwitcher; private boolean mShouldSwitchToLastSubtype = true; @@ -422,7 +423,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction } // Has to be package-visible for unit tests - /* package for test */ + @UsedForTesting void loadSettings() { // Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged() // is not guaranteed. It may even be called at the same time on a different thread. @@ -1848,7 +1849,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // TODO: make this private // Outside LatinIME, only used by the test suite. - /* package for tests */ + @UsedForTesting boolean isShowingPunctuationList() { if (mSuggestionStripView == null) return false; return mCurrentSettings.mSuggestPuncList == mSuggestionStripView.getSuggestions(); @@ -2232,7 +2233,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // TODO: Make this private // Outside LatinIME, only used by the {@link InputTestsBase} test suite. - /* package for test */ + @UsedForTesting void loadKeyboard() { // When the device locale is changed in SetupWizard etc., this method may get called via // onConfigurationChanged before SoftInputWindow is shown. diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index f0e3b4ebd..fea7215ff 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -19,6 +19,7 @@ package com.android.inputmethod.latin; import android.content.Context; import android.text.TextUtils; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; @@ -71,7 +72,8 @@ public final class Suggest { mLocale = locale; } - /* package for test */ Suggest(final Context context, final File dictionary, + @UsedForTesting + Suggest(final Context context, final File dictionary, final long startOffset, final long length, final Locale locale) { final Dictionary mainDict = DictionaryFactory.createDictionaryForTest(context, dictionary, startOffset, length /* useFullEditDistance */, false, locale); diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java index e39011145..787197755 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java @@ -18,6 +18,7 @@ package com.android.inputmethod.latin; import android.util.Log; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.makedict.BinaryDictIOUtils; import com.android.inputmethod.latin.makedict.BinaryDictInputOutput; import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.FusionDictionaryBufferInterface; @@ -129,7 +130,8 @@ public final class UserHistoryDictIOUtils { /** * Constructs a new FusionDictionary from BigramDictionaryInterface. */ - /* packages for test */ static FusionDictionary constructFusionDictionary( + @UsedForTesting + static FusionDictionary constructFusionDictionary( final BigramDictionaryInterface dict, final UserHistoryDictionaryBigramList bigrams) { final FusionDictionary fusionDict = new FusionDictionary(new Node(), new FusionDictionary.DictionaryOptions(new HashMap(), false, @@ -193,7 +195,8 @@ public final class UserHistoryDictIOUtils { /** * Adds all unigrams and bigrams in maps to OnAddWordListener. */ - /* package for test */ static void addWordsFromWordMap(final Map unigrams, + @UsedForTesting + static void addWordsFromWordMap(final Map unigrams, final Map frequencies, final Map> bigrams, final OnAddWordListener to) { for (Map.Entry entry : unigrams.entrySet()) { diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java index 3615fa1fb..639c9b915 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java @@ -21,6 +21,7 @@ import android.content.SharedPreferences; import android.os.AsyncTask; 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.UserHistoryDictIOUtils.BigramDictionaryInterface; @@ -75,7 +76,7 @@ public final class UserHistoryDictionary extends ExpandableDictionary { private final SharedPreferences mPrefs; // Should always be false except when we use this class for test - /* package for test */ boolean isTest = false; + @UsedForTesting boolean isTest = false; private static final ConcurrentHashMap> sLangDictCache = CollectionUtils.newConcurrentHashMap(); @@ -390,6 +391,7 @@ public final class UserHistoryDictionary extends ExpandableDictionary { } } + @UsedForTesting void forceAddWordForTest(final String word1, final String word2, final boolean isValid) { mBigramListLock.lock(); try { diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 40e089f3a..05f2d933c 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -16,6 +16,7 @@ package com.android.inputmethod.latin.makedict; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.CharEncoding; import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.FusionDictionaryBufferInterface; @@ -167,6 +168,7 @@ public final class BinaryDictIOUtils { * @throws IOException * @throws UnsupportedFormatException */ + @UsedForTesting public static int getTerminalPosition(final FusionDictionaryBufferInterface buffer, final String word) throws IOException, UnsupportedFormatException { if (word == null) return FormatSpec.NOT_VALID_WORD; @@ -254,6 +256,7 @@ public final class BinaryDictIOUtils { * @throws IOException * @throws UnsupportedFormatException */ + @UsedForTesting public static void deleteWord(final FusionDictionaryBufferInterface buffer, final String word) throws IOException, UnsupportedFormatException { buffer.position(0); @@ -706,6 +709,8 @@ public final class BinaryDictIOUtils { * @throws UnsupportedFormatException */ // TODO: Support batch insertion. + // TODO: Remove @UsedForTesting once UserHistoryDictionary is implemented by BinaryDictionary. + @UsedForTesting public static void insertWord(final FusionDictionaryBufferInterface buffer, final OutputStream destination, final String word, final int frequency, final ArrayList bigramStrings, @@ -959,6 +964,7 @@ public final class BinaryDictIOUtils { * @throws IOException * @throws UnsupportedFormatException */ + @UsedForTesting public static CharGroupInfo findWordFromBuffer(final FusionDictionaryBufferInterface buffer, final String word) throws IOException, UnsupportedFormatException { int position = getTerminalPosition(buffer, word); diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 2d39094ff..277796dd2 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -16,6 +16,7 @@ package com.android.inputmethod.latin.makedict; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader; import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions; import com.android.inputmethod.latin.makedict.FusionDictionary.CharGroup; @@ -1651,6 +1652,7 @@ public final class BinaryDictInputOutput { * @param dict an optional dictionary to add words to, or null. * @return the created (or merged) dictionary. */ + @UsedForTesting public static FusionDictionary readDictionaryBinary( final FusionDictionaryBufferInterface buffer, final FusionDictionary dict) throws IOException, UnsupportedFormatException { diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java index 11bb97031..6c0d79c2b 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java @@ -16,6 +16,7 @@ package com.android.inputmethod.latin.spellcheck; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.CollectionUtils; import com.android.inputmethod.latin.Constants; @@ -23,7 +24,7 @@ import com.android.inputmethod.latin.Constants; import java.util.TreeMap; public final class SpellCheckerProximityInfo { - /* public for test */ + @UsedForTesting final public static int NUL = Constants.NOT_A_CODE; // This must be the same as MAX_PROXIMITY_CHARS_SIZE else it will not work inside diff --git a/tools/dicttool/Android.mk b/tools/dicttool/Android.mk index 5bd836a01..159c1c160 100644 --- a/tools/dicttool/Android.mk +++ b/tools/dicttool/Android.mk @@ -16,14 +16,18 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LATINIME_CORE_SOURCE_DIRECTORY := ../../java/src/com/android/inputmethod/latin +LATINIME_BASE_SOURCE_DIRECTORY := ../../java/src/com/android/inputmethod +LATINIME_CORE_SOURCE_DIRECTORY := $(LATINIME_BASE_SOURCE_DIRECTORY)/latin +LATINIME_ANNOTATIONS_SOURCE_DIRECTORY := $(LATINIME_BASE_SOURCE_DIRECTORY)/annotations MAKEDICT_CORE_SOURCE_DIRECTORY := $(LATINIME_CORE_SOURCE_DIRECTORY)/makedict LOCAL_MAIN_SRC_FILES := $(call all-java-files-under,$(MAKEDICT_CORE_SOURCE_DIRECTORY)) LOCAL_TOOL_SRC_FILES := $(call all-java-files-under,src) +LOCAL_ANNOTATIONS_SRC_FILES := $(call all-java-files-under,$(LATINIME_ANNOTATIONS_SOURCE_DIRECTORY)) LOCAL_SRC_FILES := $(LOCAL_TOOL_SRC_FILES) \ $(filter-out $(addprefix %/, $(notdir $(LOCAL_TOOL_SRC_FILES))), $(LOCAL_MAIN_SRC_FILES)) \ $(call all-java-files-under,tests) \ + $(LOCAL_ANNOTATIONS_SRC_FILES) \ $(LATINIME_CORE_SOURCE_DIRECTORY)/Constants.java LOCAL_JAR_MANIFEST := etc/manifest.txt diff --git a/tools/dicttool/tests/com/android/inputmethod/latin/makedict/BinaryDictInputOutputTest.java b/tools/dicttool/tests/com/android/inputmethod/latin/makedict/BinaryDictInputOutputTest.java index 88589b815..096902879 100644 --- a/tools/dicttool/tests/com/android/inputmethod/latin/makedict/BinaryDictInputOutputTest.java +++ b/tools/dicttool/tests/com/android/inputmethod/latin/makedict/BinaryDictInputOutputTest.java @@ -19,24 +19,15 @@ package com.android.inputmethod.latin.makedict; import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions; import com.android.inputmethod.latin.makedict.FusionDictionary.Node; +import junit.framework.TestCase; + import java.util.ArrayList; import java.util.HashMap; -import junit.framework.TestCase; - /** * Unit tests for BinaryDictInputOutput. */ public class BinaryDictInputOutputTest extends TestCase { - - public void setUp() throws Exception { - super.setUp(); - } - - public void tearDown() throws Exception { - super.tearDown(); - } - // Test the flattened array contains the expected number of nodes, and // that it does not contain any duplicates. public void testFlattenNodes() { @@ -55,5 +46,4 @@ public class BinaryDictInputOutputTest extends TestCase { assertFalse("Flattened array contained the same node twice", result.contains(n)); } } - } diff --git a/tools/dicttool/tests/etc/test-dicttool.sh b/tools/dicttool/tests/etc/test-dicttool.sh index 8834611cd..1283be21a 100755 --- a/tools/dicttool/tests/etc/test-dicttool.sh +++ b/tools/dicttool/tests/etc/test-dicttool.sh @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -java -classpath ${ANDROID_HOST_OUT}/framework/junit.jar:${ANDROID_HOST_OUT}/../common/obj/JAVA_LIBRARIES/dicttool_intermediates/classes junit.textui.TestRunner com.android.inputmethod.latin.makedict.BinaryDictInputOutputTest +java -classpath ${ANDROID_HOST_OUT}/framework/junit.jar:${ANDROID_HOST_OUT}/framework/dicttool_aosp.jar junit.textui.TestRunner com.android.inputmethod.latin.makedict.BinaryDictInputOutputTest diff --git a/tools/maketext/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl b/tools/maketext/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl index 774094cd7..15aea9084 100644 --- a/tools/maketext/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl +++ b/tools/maketext/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl @@ -19,6 +19,7 @@ package com.android.inputmethod.keyboard.internal; import android.content.Context; import android.content.res.Resources; +import com.android.inputmethod.annotations.VisibleForTesting; import com.android.inputmethod.latin.CollectionUtils; import com.android.inputmethod.latin.R; @@ -64,7 +65,7 @@ public final class KeyboardTextsSet { loadStringResourcesInternal(context, RESOURCE_NAMES, R.string.english_ime_name); } - /* package for test */ + @VisibleForTesting void loadStringResourcesInternal(Context context, final String[] resourceNames, int referenceId) { final Resources res = context.getResources(); -- cgit v1.2.3-83-g751a From f960eb186d63aa4f9fecd22f036fc8724d39d949 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Tue, 23 Oct 2012 11:30:39 +0900 Subject: Don't put spaces after characters that don't take one Bug: 7393639 Change-Id: I1245a7b5077e554642838d6856ce269ca7f91988 --- java/src/com/android/inputmethod/latin/LatinIME.java | 6 +++++- java/src/com/android/inputmethod/latin/SettingsValues.java | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index c1b1751f1..1ade3c422 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1431,8 +1431,12 @@ public final class LatinIME extends InputMethodService implements KeyboardAction mSpaceState = SPACE_STATE_PHANTOM; } else { final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor(); + // TODO: reverse this logic. We should have the means to determine whether a character + // should usually be followed by a space, and it should be more readable. if (Constants.NOT_A_CODE != codePointBeforeCursor - && !Character.isWhitespace(codePointBeforeCursor)) { + && !Character.isWhitespace(codePointBeforeCursor) + && !mCurrentSettings.isPhantomSpacePromotingSymbol(codePointBeforeCursor) + && !mCurrentSettings.isWeakSpaceStripper(codePointBeforeCursor)) { mSpaceState = SPACE_STATE_PHANTOM; } } diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 1c5864bce..2a778aa0d 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -254,11 +254,13 @@ public final class SettingsValues { return mSymbolsExcludedFromWordSeparators.contains(String.valueOf((char)code)); } + // TODO: use "Phantom" instead of "Weak" in this method name public boolean isWeakSpaceStripper(final int code) { // TODO: this does not work if the code does not fit in a char return mWeakSpaceStrippers.contains(String.valueOf((char)code)); } + // TODO: use "Phantom" instead of "Weak" in this method name public boolean isWeakSpaceSwapper(final int code) { // TODO: this does not work if the code does not fit in a char return mWeakSpaceSwappers.contains(String.valueOf((char)code)); -- cgit v1.2.3-83-g751a From 9bb4eebf48f3e15bcdfe37d73f26693bd4eaf0f4 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Mon, 22 Oct 2012 17:00:39 +0900 Subject: Add reader and writer for the combined dict format. This introduces a new textual format for the dictionary that combines words, bigrams and shortcuts to avoid complexity. It is also extensible to n-grams to fool-prof for the future, and easier to read than XML. Bug: 7388540 Change-Id: I942bbad51bd0c905a5a54c278667563fd6dd66ec --- .../latin/BinaryDictionaryFileDumper.java | 8 +- .../latin/dicttool/CombinedInputOutput.java | 238 +++++++++++++++++++++ .../latin/dicttool/DictionaryMaker.java | 91 ++++++-- .../inputmethod/latin/dicttool/Dicttool.java | 1 + 4 files changed, 319 insertions(+), 19 deletions(-) create mode 100644 tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index bed31a7d1..b0b65edb6 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -149,13 +149,7 @@ public final class BinaryDictionaryFileDumper { final Uri.Builder wordListUriBuilder = getProviderUriBuilder(id); final String finalFileName = BinaryDictionaryGetter.getCacheFileName(id, locale, context); - String tempFileName; - try { - tempFileName = BinaryDictionaryGetter.getTempFileName(id, context); - } catch (IOException e) { - Log.e(TAG, "Can't open the temporary file", e); - return null; - } + final String tempFileName = BinaryDictionaryGetter.getTempFileName(id, context); for (int mode = MODE_MIN; mode <= MODE_MAX; ++mode) { InputStream originalSourceStream = null; diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java new file mode 100644 index 000000000..c17667536 --- /dev/null +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.android.inputmethod.latin.dicttool; + +import com.android.inputmethod.latin.makedict.FusionDictionary; +import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions; +import com.android.inputmethod.latin.makedict.FusionDictionary.Node; +import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; +import com.android.inputmethod.latin.makedict.Word; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Writer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.TreeSet; + +/** + * Reads and writes combined format for a FusionDictionary. + * + * All functions in this class are static. + */ +public class CombinedInputOutput { + + private static final String DICTIONARY_TAG = "dictionary"; + private static final String BIGRAM_TAG = "bigram"; + private static final String SHORTCUT_TAG = "shortcut"; + private static final String FREQUENCY_TAG = "f"; + private static final String WORD_TAG = "word"; + private static final String NOT_A_WORD_TAG = "not_a_word"; + private static final String WHITELIST_TAG = "whitelist"; + private static final String OPTIONS_TAG = "options"; + private static final String GERMAN_UMLAUT_PROCESSING_OPTION = "german_umlaut_processing"; + private static final String FRENCH_LIGATURE_PROCESSING_OPTION = "french_ligature_processing"; + + /** + * Basic test to find out whether the file is in the combined format or not. + * + * Concretely this only tests the header line. + * + * @param filename The name of the file to test. + * @return true if the file is in the combined format, false otherwise + */ + public static boolean isCombinedDictionary(final String filename) { + BufferedReader reader = null; + try { + reader = new BufferedReader(new FileReader(new File(filename))); + final String firstLine = reader.readLine(); + return firstLine.matches("^" + DICTIONARY_TAG + "=[^:]+(:[^=]+=[^:]+)*"); + } catch (FileNotFoundException e) { + return false; + } catch (IOException e) { + return false; + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + // do nothing + } + } + } + } + + /** + * Reads a dictionary from a combined format file. + * + * This is the public method that will read a combined file and return the corresponding memory + * representation. + * + * @param source the file to read the data from. + * @return the in-memory representation of the dictionary. + */ + public static FusionDictionary readDictionaryCombined(final InputStream source) + throws IOException { + final BufferedReader reader = new BufferedReader(new InputStreamReader(source, "UTF-8")); + final String headerLine = reader.readLine(); + final String header[] = headerLine.split(","); + final HashMap attributes = new HashMap(); + for (String item : header) { + final String keyValue[] = item.split("="); + if (2 != keyValue.length) { + throw new RuntimeException("Wrong header format : " + headerLine); + } + attributes.put(keyValue[0], keyValue[1]); + } + + final boolean processUmlauts = + GERMAN_UMLAUT_PROCESSING_OPTION.equals(attributes.get(OPTIONS_TAG)); + final boolean processLigatures = + FRENCH_LIGATURE_PROCESSING_OPTION.equals(attributes.get(OPTIONS_TAG)); + attributes.remove(OPTIONS_TAG); + final FusionDictionary dict = new FusionDictionary(new Node(), new DictionaryOptions( + attributes, processUmlauts, processLigatures)); + + String line; + String word = null; + int freq = 0; + boolean isNotAWord = false; + ArrayList bigrams = new ArrayList(); + ArrayList shortcuts = new ArrayList(); + while (null != (line = reader.readLine())) { + final String args[] = line.trim().split(","); + if (args[0].matches(WORD_TAG + "=.*")) { + if (null != word) { + dict.add(word, freq, shortcuts.isEmpty() ? null : shortcuts, isNotAWord); + for (WeightedString s : bigrams) { + dict.setBigram(word, s.mWord, s.mFrequency); + } + } + if (!shortcuts.isEmpty()) shortcuts = new ArrayList(); + if (!bigrams.isEmpty()) bigrams = new ArrayList(); + isNotAWord = false; + for (String param : args) { + final String params[] = param.split("=", 2); + if (2 != params.length) throw new RuntimeException("Wrong format : " + line); + if (WORD_TAG.equals(params[0])) { + word = params[1]; + } else if (FREQUENCY_TAG.equals(params[0])) { + freq = Integer.parseInt(params[1]); + } else if (NOT_A_WORD_TAG.equals(params[0])) { + isNotAWord = "true".equals(params[1]); + } + } + } else if (args[0].matches(SHORTCUT_TAG + "=.*")) { + String shortcut = null; + int shortcutFreq = 0; + for (String param : args) { + final String params[] = param.split("=", 2); + if (2 != params.length) throw new RuntimeException("Wrong format : " + line); + if (SHORTCUT_TAG.equals(params[0])) { + shortcut = params[1]; + } else if (FREQUENCY_TAG.equals(params[0])) { + shortcutFreq = + WHITELIST_TAG.equals(params[1]) ? 15 : Integer.parseInt(params[1]); + } + } + if (null != shortcut) { + shortcuts.add(new WeightedString(shortcut, shortcutFreq)); + } else { + throw new RuntimeException("Wrong format : " + line); + } + } else if (args[0].matches(BIGRAM_TAG + "=.*")) { + String secondWordOfBigram = null; + int bigramFreq = 0; + for (String param : args) { + final String params[] = param.split("=", 2); + if (2 != params.length) throw new RuntimeException("Wrong format : " + line); + if (BIGRAM_TAG.equals(params[0])) { + secondWordOfBigram = params[1]; + } else if (FREQUENCY_TAG.equals(params[0])) { + bigramFreq = Integer.parseInt(params[1]); + } + } + if (null != secondWordOfBigram) { + bigrams.add(new WeightedString(secondWordOfBigram, bigramFreq)); + } else { + throw new RuntimeException("Wrong format : " + line); + } + } + } + if (null != word) { + dict.add(word, freq, shortcuts.isEmpty() ? null : shortcuts, isNotAWord); + for (WeightedString s : bigrams) { + dict.setBigram(word, s.mWord, s.mFrequency); + } + } + + return dict; + } + + /** + * Writes a dictionary to a combined file. + * + * @param destination a destination stream to write to. + * @param dict the dictionary to write. + */ + public static void writeDictionaryCombined(Writer destination, FusionDictionary dict) + throws IOException { + final TreeSet set = new TreeSet(); + for (Word word : dict) { + set.add(word); // This for ordering by frequency, then by asciibetic order + } + final HashMap options = dict.mOptions.mAttributes; + destination.write(DICTIONARY_TAG + "="); + if (options.containsKey(DICTIONARY_TAG)) { + destination.write(options.get(DICTIONARY_TAG)); + options.remove(DICTIONARY_TAG); + } + if (dict.mOptions.mGermanUmlautProcessing) { + destination.write("," + OPTIONS_TAG + "=" + GERMAN_UMLAUT_PROCESSING_OPTION); + } else if (dict.mOptions.mFrenchLigatureProcessing) { + destination.write("," + OPTIONS_TAG + "=" + FRENCH_LIGATURE_PROCESSING_OPTION); + } + for (final String key : dict.mOptions.mAttributes.keySet()) { + final String value = dict.mOptions.mAttributes.get(key); + destination.write("," + key + "=" + value); + } + destination.write("\n"); + for (Word word : set) { + destination.write("\t" + WORD_TAG + "=" + word.mWord + "," + + FREQUENCY_TAG + "=" + word.mFrequency + + (word.mIsNotAWord ? "," + NOT_A_WORD_TAG + "=true\n" : "\n")); + if (null != word.mShortcutTargets) { + for (WeightedString target : word.mShortcutTargets) { + destination.write("\t\t" + SHORTCUT_TAG + "=" + target.mWord + "," + + FREQUENCY_TAG + "=" + target.mFrequency + "\n"); + } + } + if (null != word.mBigrams) { + for (WeightedString bigram : word.mBigrams) { + destination.write("\t\t" + BIGRAM_TAG + "=" + bigram.mWord + "," + + FREQUENCY_TAG + "=" + bigram.mFrequency + "\n"); + } + } + } + destination.close(); + } +} diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java index 2cdd83e96..561db7363 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java @@ -52,13 +52,16 @@ public class DictionaryMaker { private static final String OPTION_INPUT_SHORTCUT_XML = "-c"; private static final String OPTION_OUTPUT_BINARY = "-d"; private static final String OPTION_OUTPUT_XML = "-x"; + private static final String OPTION_OUTPUT_COMBINED = "-o"; private static final String OPTION_HELP = "-h"; public final String mInputBinary; + public final String mInputCombined; public final String mInputUnigramXml; public final String mInputShortcutXml; public final String mInputBigramXml; public final String mOutputBinary; public final String mOutputXml; + public final String mOutputCombined; public final int mOutputBinaryFormatVersion; private void checkIntegrity() throws IOException { @@ -66,28 +69,38 @@ public class DictionaryMaker { checkHasAtLeastOneOutput(); checkNotSameFile(mInputBinary, mOutputBinary); checkNotSameFile(mInputBinary, mOutputXml); + checkNotSameFile(mInputCombined, mOutputBinary); + checkNotSameFile(mInputCombined, mOutputXml); checkNotSameFile(mInputUnigramXml, mOutputBinary); checkNotSameFile(mInputUnigramXml, mOutputXml); + checkNotSameFile(mInputUnigramXml, mOutputCombined); checkNotSameFile(mInputShortcutXml, mOutputBinary); checkNotSameFile(mInputShortcutXml, mOutputXml); + checkNotSameFile(mInputShortcutXml, mOutputCombined); checkNotSameFile(mInputBigramXml, mOutputBinary); checkNotSameFile(mInputBigramXml, mOutputXml); + checkNotSameFile(mInputBigramXml, mOutputCombined); checkNotSameFile(mOutputBinary, mOutputXml); + checkNotSameFile(mOutputBinary, mOutputCombined); + checkNotSameFile(mOutputXml, mOutputCombined); } private void checkHasExactlyOneInput() { - if (null == mInputUnigramXml && null == mInputBinary) { + if (null == mInputUnigramXml && null == mInputBinary && null == mInputCombined) { throw new RuntimeException("No input file specified"); - } else if (null != mInputUnigramXml && null != mInputBinary) { - throw new RuntimeException("Both input XML and binary specified"); - } else if (null != mInputBinary && null != mInputBigramXml) { - throw new RuntimeException("Cannot specify a binary input and a separate bigram " - + "file"); + } else if ((null != mInputUnigramXml && null != mInputBinary) + || (null != mInputUnigramXml && null != mInputCombined) + || (null != mInputBinary && null != mInputCombined)) { + throw new RuntimeException("Several input files specified"); + } else if ((null != mInputBinary || null != mInputCombined) + && (null != mInputBigramXml || null != mInputShortcutXml)) { + throw new RuntimeException("Separate bigrams/shortcut files are only supported" + + " with XML input (other formats include bigrams and shortcuts already)"); } } private void checkHasAtLeastOneOutput() { - if (null == mOutputBinary && null == mOutputXml) { + if (null == mOutputBinary && null == mOutputXml && null == mOutputCombined) { throw new RuntimeException("No output specified"); } } @@ -111,17 +124,16 @@ public class DictionaryMaker { public static String getHelp() { return "Usage: makedict " + "[-s [-b ] [-c ] " + + "| [-s ] [-d ] [-x ] " + + " [-o ]" + "[-1] [-2] [-3]\n" + "\n" + " Converts a source dictionary file to one or several outputs.\n" + " Source can be an XML file, with an optional XML bigrams file, or a\n" + " binary dictionary file.\n" - + " Binary version 1 (Ice Cream Sandwich), 2 (Jelly Bean), 3 and XML outputs\n" - + " are supported. All three can be output at the same time, but the same\n" - + " output format cannot be specified several times. The behavior is\n" - + " unspecified if the same file is specified for input and output, or for\n" - + " several outputs."; + + " Binary version 1 (Ice Cream Sandwich), 2 (Jelly Bean), 3, XML and\n" + + " combined format outputs are supported."; } public Arguments(String[] argsArray) throws IOException { @@ -130,11 +142,13 @@ public class DictionaryMaker { displayHelp(); } String inputBinary = null; + String inputCombined = null; String inputUnigramXml = null; String inputShortcutXml = null; String inputBigramXml = null; String outputBinary = null; String outputXml = null; + String outputCombined = null; int outputBinaryFormatVersion = 2; // the default version is 2. while (!args.isEmpty()) { @@ -160,6 +174,8 @@ public class DictionaryMaker { if (OPTION_INPUT_SOURCE.equals(arg)) { if (BinaryDictInputOutput.isBinaryDictionary(filename)) { inputBinary = filename; + } else if (CombinedInputOutput.isCombinedDictionary(filename)) { + inputCombined = filename; } else { inputUnigramXml = filename; } @@ -171,6 +187,8 @@ public class DictionaryMaker { outputBinary = filename; } else if (OPTION_OUTPUT_XML.equals(arg)) { outputXml = filename; + } else if (OPTION_OUTPUT_COMBINED.equals(arg)) { + outputCombined = filename; } else { throw new IllegalArgumentException("Unknown option : " + arg); } @@ -179,6 +197,8 @@ public class DictionaryMaker { if (null == inputBinary && null == inputUnigramXml) { if (BinaryDictInputOutput.isBinaryDictionary(arg)) { inputBinary = arg; + } else if (CombinedInputOutput.isCombinedDictionary(arg)) { + inputCombined = arg; } else { inputUnigramXml = arg; } @@ -191,11 +211,13 @@ public class DictionaryMaker { } mInputBinary = inputBinary; + mInputCombined = inputCombined; mInputUnigramXml = inputUnigramXml; mInputShortcutXml = inputShortcutXml; mInputBigramXml = inputBigramXml; mOutputBinary = outputBinary; mOutputXml = outputXml; + mOutputCombined = outputCombined; mOutputBinaryFormatVersion = outputBinaryFormatVersion; checkIntegrity(); } @@ -220,6 +242,8 @@ public class DictionaryMaker { SAXException, FileNotFoundException { if (null != args.mInputBinary) { return readBinaryFile(args.mInputBinary); + } else if (null != args.mInputCombined) { + return readCombinedFile(args.mInputCombined); } else if (null != args.mInputUnigramXml) { return readXmlFile(args.mInputUnigramXml, args.mInputShortcutXml, args.mInputBigramXml); } else { @@ -258,6 +282,32 @@ public class DictionaryMaker { } } + /** + * Read a dictionary from the name of a combined file. + * + * @param combinedFilename the name of the file in the combined format. + * @return the read dictionary. + * @throws FileNotFoundException if the file can't be found + * @throws IOException if the input file can't be read + */ + private static FusionDictionary readCombinedFile(final String combinedFilename) + throws FileNotFoundException, IOException { + FileInputStream inStream = null; + try { + final File file = new File(combinedFilename); + inStream = new FileInputStream(file); + return CombinedInputOutput.readDictionaryCombined(inStream); + } finally { + if (null != inStream) { + try { + inStream.close(); + } catch (IOException e) { + // do nothing + } + } + } + } + /** * Read a dictionary from a unigram XML file, and optionally a bigram XML file. * @@ -299,6 +349,9 @@ public class DictionaryMaker { if (null != args.mOutputXml) { writeXmlDictionary(args.mOutputXml, dict); } + if (null != args.mOutputCombined) { + writeCombinedDictionary(args.mOutputCombined, dict); + } } /** @@ -332,4 +385,18 @@ public class DictionaryMaker { XmlDictInputOutput.writeDictionaryXml(new BufferedWriter(new FileWriter(outputFilename)), dict); } + + /** + * Write the dictionary in the combined format to the specified filename. + * + * @param outputFilename the name of the file to write to. + * @param dict the dictionary to write. + * @throws FileNotFoundException if the output file can't be created. + * @throws IOException if the output file can't be written to. + */ + private static void writeCombinedDictionary(final String outputFilename, + final FusionDictionary dict) throws FileNotFoundException, IOException { + CombinedInputOutput.writeDictionaryCombined( + new BufferedWriter(new FileWriter(outputFilename)), dict); + } } diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Dicttool.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Dicttool.java index bf417fb5a..75ce104e0 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Dicttool.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Dicttool.java @@ -80,6 +80,7 @@ public class Dicttool { } catch (Exception e) { System.out.println("Exception while processing command " + command.getClass().getSimpleName() + " : " + e); + e.printStackTrace(); return; } } -- cgit v1.2.3-83-g751a From 1e0cc86b6f77e69273f41f6f291af25968a790f6 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Tue, 23 Oct 2012 15:34:03 +0900 Subject: Fix the build. It seems this change snuck out from a previous version. Change-Id: I9c33d51273732b1d55bfd60f0957184c86fa88ab --- .../com/android/inputmethod/latin/BinaryDictionaryFileDumper.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index b0b65edb6..bed31a7d1 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -149,7 +149,13 @@ public final class BinaryDictionaryFileDumper { final Uri.Builder wordListUriBuilder = getProviderUriBuilder(id); final String finalFileName = BinaryDictionaryGetter.getCacheFileName(id, locale, context); - final String tempFileName = BinaryDictionaryGetter.getTempFileName(id, context); + String tempFileName; + try { + tempFileName = BinaryDictionaryGetter.getTempFileName(id, context); + } catch (IOException e) { + Log.e(TAG, "Can't open the temporary file", e); + return null; + } for (int mode = MODE_MIN; mode <= MODE_MAX; ++mode) { InputStream originalSourceStream = null; -- cgit v1.2.3-83-g751a From c59c7419878d91852420bcc6663e7dc6aaf446fd Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Tue, 23 Oct 2012 12:07:57 +0900 Subject: Return the correct bigram frequency The "correct" bigram frequency is now returned by the reading code. However, as the binary format represents the frequency in a lossy manner, the frequency is not guaranteed to be the exact same as the one in the source text format - only a close enough value. It is however the exact same value seen by the native code. Bug: 7395653 Change-Id: I49199ef18901c671189912b3550623e9643baedd --- .../latin/makedict/BinaryDictInputOutput.java | 33 ++++++++++++++-------- 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 277796dd2..da5236974 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -1374,7 +1374,8 @@ public final class BinaryDictInputOutput { // of this method. Since it performs direct, unbuffered random access to the file and // may be called hundreds of thousands of times, the resulting performance is not // reasonable without some kind of cache. Thus: - private static TreeMap wordCache = new TreeMap(); + private static TreeMap wordCache = + new TreeMap(); /** * Finds, as a string, the word at the address passed as an argument. * @@ -1382,15 +1383,15 @@ public final class BinaryDictInputOutput { * @param headerSize the size of the header. * @param address the address to seek. * @param formatOptions file format options. - * @return the word, as a string. + * @return the word with its frequency, as a weighted string. */ - /* packages for tests */ static String getWordAtAddress( + /* package for tests */ static WeightedString getWordAtAddress( final FusionDictionaryBufferInterface buffer, final int headerSize, final int address, final FormatOptions formatOptions) { - final String cachedString = wordCache.get(address); + final WeightedString cachedString = wordCache.get(address); if (null != cachedString) return cachedString; - final String result; + final WeightedString result; final int originalPointer = buffer.position(); buffer.position(address); @@ -1406,14 +1407,17 @@ public final class BinaryDictInputOutput { return result; } + // TODO: static!? This will behave erratically when used in multi-threaded code. + // We need to fix this private static int[] sGetWordBuffer = new int[FormatSpec.MAX_WORD_LENGTH]; - private static String getWordAtAddressWithParentAddress( + private static WeightedString getWordAtAddressWithParentAddress( final FusionDictionaryBufferInterface buffer, final int headerSize, final int address, final FormatOptions options) { final StringBuilder builder = new StringBuilder(); int currentAddress = address; int index = FormatSpec.MAX_WORD_LENGTH - 1; + int frequency = Integer.MIN_VALUE; // the length of the path from the root to the leaf is limited by MAX_WORD_LENGTH for (int count = 0; count < FormatSpec.MAX_WORD_LENGTH; ++count) { CharGroupInfo currentInfo; @@ -1428,6 +1432,7 @@ public final class BinaryDictInputOutput { MakedictLog.d("Too many jumps - probably a bug"); } } while (isMovedGroup(currentInfo.mFlags, options)); + if (Integer.MIN_VALUE == frequency) frequency = currentInfo.mFrequency; for (int i = 0; i < currentInfo.mCharacters.length; ++i) { sGetWordBuffer[index--] = currentInfo.mCharacters[currentInfo.mCharacters.length - i - 1]; @@ -1436,17 +1441,19 @@ public final class BinaryDictInputOutput { currentAddress = currentInfo.mParentAddress + currentInfo.mOriginalAddress; } - return new String(sGetWordBuffer, index + 1, FormatSpec.MAX_WORD_LENGTH - index - 1); + return new WeightedString( + new String(sGetWordBuffer, index + 1, FormatSpec.MAX_WORD_LENGTH - index - 1), + frequency); } - private static String getWordAtAddressWithoutParentAddress( + private static WeightedString getWordAtAddressWithoutParentAddress( final FusionDictionaryBufferInterface buffer, final int headerSize, final int address, final FormatOptions options) { buffer.position(headerSize); final int count = readCharGroupCount(buffer); int groupOffset = getGroupCountSize(count); final StringBuilder builder = new StringBuilder(); - String result = null; + WeightedString result = null; CharGroupInfo last = null; for (int i = count - 1; i >= 0; --i) { @@ -1454,7 +1461,7 @@ public final class BinaryDictInputOutput { groupOffset = info.mEndAddress; if (info.mOriginalAddress == address) { builder.append(new String(info.mCharacters, 0, info.mCharacters.length)); - result = builder.toString(); + result = new WeightedString(builder.toString(), info.mFrequency); break; // and return } if (hasChildrenAddress(info.mChildrenAddress)) { @@ -1515,9 +1522,11 @@ public final class BinaryDictInputOutput { if (null != info.mBigrams) { bigrams = new ArrayList(); for (PendingAttribute bigram : info.mBigrams) { - final String word = getWordAtAddress( + final WeightedString word = getWordAtAddress( buffer, headerSize, bigram.mAddress, options); - bigrams.add(new WeightedString(word, bigram.mFrequency)); + final int reconstructedFrequency = + reconstructBigramFrequency(word.mFrequency, bigram.mFrequency); + bigrams.add(new WeightedString(word.mWord, reconstructedFrequency)); } } if (hasChildrenAddress(info.mChildrenAddress)) { -- cgit v1.2.3-83-g751a From ddb0bcc051c1e9f2706f3702f0bb3135e4352f7b Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Wed, 24 Oct 2012 13:24:59 +0900 Subject: Fix a bug where a bigram would be ignored Bug: 7403386 Change-Id: I89f495d07f7059a9f1ccd97d487c2f2657a8ebd2 --- java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java index 6f1faa192..7fd13d78b 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java +++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java @@ -358,6 +358,10 @@ public final class FusionDictionary implements Iterable { if (charGroup2 == null) { add(getCodePoints(word2), 0, null, false /* isNotAWord */, false /* isBlacklistEntry */); + // The chargroup for the first word may have moved by the above insertion, + // if word1 and word2 share a common stem that happens not to have been + // a cutting point until now. In this case, we need to refresh charGroup. + charGroup = findWordInTree(mRoot, word1); } charGroup.addBigram(word2, frequency); } else { -- cgit v1.2.3-83-g751a From b3c98901c5fc1460b54cdf27d74405f27c88e74b Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Tue, 23 Oct 2012 17:14:12 +0900 Subject: Add auto detection and decoding of dictionary files. (A2) Bug: 7388852 Change-Id: I25e755fc15f5b383acc046f668e9681efa4f0c2f --- .../latin/makedict/BinaryDictInputOutput.java | 11 ++- .../latin/makedict/FusionDictionary.java | 6 ++ .../latin/dicttool/BinaryDictOffdeviceUtils.java | 82 ++++++++++++++-- .../inputmethod/latin/dicttool/Compress.java | 14 +-- .../dicttool/BinaryDictOffdeviceUtilsTests.java | 106 +++++++++++++++++++++ tools/dicttool/tests/etc/test-dicttool.sh | 1 + 6 files changed, 206 insertions(+), 14 deletions(-) create mode 100644 tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index da5236974..031306e1d 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -1698,6 +1698,14 @@ public final class BinaryDictInputOutput { return newDict; } + /** + * Helper method to pass a file name instead of a File object to isBinaryDictionary. + */ + public static boolean isBinaryDictionary(final String filename) { + final File file = new File(filename); + return isBinaryDictionary(file); + } + /** * Basic test to find out whether the file is a binary dictionary or not. * @@ -1706,10 +1714,9 @@ public final class BinaryDictInputOutput { * @param filename The name of the file to test. * @return true if it's a binary dictionary, false otherwise */ - public static boolean isBinaryDictionary(final String filename) { + public static boolean isBinaryDictionary(final File file) { FileInputStream inStream = null; try { - final File file = new File(filename); inStream = new FileInputStream(file); final ByteBuffer buffer = inStream.getChannel().map( FileChannel.MapMode.READ_ONLY, 0, file.length()); diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java index 7fd13d78b..44537986b 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java +++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java @@ -16,6 +16,7 @@ package com.android.inputmethod.latin.makedict; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.Constants; import java.util.ArrayList; @@ -141,6 +142,11 @@ public final class FusionDictionary implements Iterable { return NOT_A_TERMINAL != mFrequency; } + @UsedForTesting + public int getFrequency() { + return mFrequency; + } + public boolean hasSeveralChars() { assert(mChars.length > 0); return 1 < mChars.length; diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java index 83c5d9ac6..9dcd7eb42 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java @@ -16,19 +16,42 @@ package com.android.inputmethod.latin.dicttool; +import com.android.inputmethod.latin.makedict.BinaryDictInputOutput; + +import java.io.File; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayList; /** -* Class grouping utilities for offline dictionary making. -* -* Those should not be used on-device, essentially because they are quite -* liberal about I/O and performance. -*/ -public class BinaryDictOffdeviceUtils { + * Class grouping utilities for offline dictionary making. + * + * Those should not be used on-device, essentially because they are quite + * liberal about I/O and performance. + */ +public final class BinaryDictOffdeviceUtils { + // Prefix and suffix are arbitrary, the values do not really matter + private final static String PREFIX = "dicttool"; + private final static String SUFFIX = ".tmp"; + + public final static String COMPRESSION = "compression"; + + public static class DecoderChainSpec { + ArrayList mDecoderSpec = new ArrayList(); + File mFile; + public DecoderChainSpec addStep(final String stepDescription) { + mDecoderSpec.add(stepDescription); + return this; + } + } + public static void copy(final InputStream input, final OutputStream output) throws IOException { final byte[] buffer = new byte[1000]; final BufferedInputStream in = new BufferedInputStream(input); @@ -38,4 +61,51 @@ public class BinaryDictOffdeviceUtils { in.close(); out.close(); } + + /** + * Returns a decrypted/uncompressed binary dictionary. + * + * This will decrypt/uncompress any number of times as necessary until it finds the binary + * dictionary signature, and copy the decoded file to a temporary place. + * If this is not a binary dictionary, the method returns null. + */ + public static DecoderChainSpec getRawBinaryDictionaryOrNull(final File src) { + return getRawBinaryDictionaryOrNullInternal(new DecoderChainSpec(), src); + } + + private static DecoderChainSpec getRawBinaryDictionaryOrNullInternal( + final DecoderChainSpec spec, final File src) { + // TODO: arrange for the intermediary files to be deleted + if (BinaryDictInputOutput.isBinaryDictionary(src)) { + spec.mFile = src; + return spec; + } + // It's not a raw dictionary - try to see if it's compressed. + final File uncompressedFile = tryGetUncompressedFile(src); + if (null != uncompressedFile) { + final DecoderChainSpec newSpec = + getRawBinaryDictionaryOrNullInternal(spec, uncompressedFile); + if (null == newSpec) return null; + return newSpec.addStep(COMPRESSION); + } + return null; + } + + /* Try to uncompress the file passed as an argument. + * + * If the file can be uncompressed, the uncompressed version is returned. Otherwise, null + * is returned. + */ + private static File tryGetUncompressedFile(final File src) { + try { + final File dst = File.createTempFile(PREFIX, SUFFIX); + final FileOutputStream dstStream = new FileOutputStream(dst); + copy(Compress.getUncompressedStream(new BufferedInputStream(new FileInputStream(src))), + new BufferedOutputStream(dstStream)); // #copy() closes the streams + return dst; + } catch (IOException e) { + // Could not uncompress the file: presumably the file is simply not a compressed file + return null; + } + } } diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Compress.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Compress.java index 49e90ada2..072de5c01 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Compress.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Compress.java @@ -16,6 +16,8 @@ package com.android.inputmethod.latin.dicttool; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -27,12 +29,12 @@ import java.util.zip.GZIPOutputStream; public class Compress { - private static OutputStream getCompressedStream(final OutputStream out) + public static OutputStream getCompressedStream(final OutputStream out) throws java.io.IOException { return new GZIPOutputStream(out); } - private static InputStream getUncompressedStream(final InputStream in) throws IOException { + public static InputStream getUncompressedStream(final InputStream in) throws IOException { return new GZIPInputStream(in); } @@ -55,9 +57,9 @@ public class Compress { final String inFilename = mArgs.length >= 1 ? mArgs[0] : STDIN_OR_STDOUT; final String outFilename = mArgs.length >= 2 ? mArgs[1] : STDIN_OR_STDOUT; final InputStream input = inFilename.equals(STDIN_OR_STDOUT) ? System.in - : new FileInputStream(new File(inFilename)); + : new BufferedInputStream(new FileInputStream(new File(inFilename))); final OutputStream output = outFilename.equals(STDIN_OR_STDOUT) ? System.out - : new FileOutputStream(new File(outFilename)); + : new BufferedOutputStream(new FileOutputStream(new File(outFilename))); BinaryDictOffdeviceUtils.copy(input, new GZIPOutputStream(output)); } } @@ -81,9 +83,9 @@ public class Compress { final String inFilename = mArgs.length >= 1 ? mArgs[0] : STDIN_OR_STDOUT; final String outFilename = mArgs.length >= 2 ? mArgs[1] : STDIN_OR_STDOUT; final InputStream input = inFilename.equals(STDIN_OR_STDOUT) ? System.in - : new FileInputStream(new File(inFilename)); + : new BufferedInputStream(new FileInputStream(new File(inFilename))); final OutputStream output = outFilename.equals(STDIN_OR_STDOUT) ? System.out - : new FileOutputStream(new File(outFilename)); + : new BufferedOutputStream(new FileOutputStream(new File(outFilename))); BinaryDictOffdeviceUtils.copy(new GZIPInputStream(input), output); } } diff --git a/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java b/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java new file mode 100644 index 000000000..7a686e556 --- /dev/null +++ b/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin.dicttool; + +import com.android.inputmethod.latin.makedict.BinaryDictInputOutput; +import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions; +import com.android.inputmethod.latin.makedict.FusionDictionary; +import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions; +import com.android.inputmethod.latin.makedict.FusionDictionary.Node; +import com.android.inputmethod.latin.makedict.UnsupportedFormatException; + +import junit.framework.TestCase; + +import java.io.File; +import java.io.BufferedOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.util.ArrayList; +import java.util.HashMap; + +/** + * Unit tests for BinaryDictOffdeviceUtilsTests + */ +public class BinaryDictOffdeviceUtilsTests extends TestCase { + private static final int TEST_FREQ = 37; // Some arbitrary value unlikely to happen by chance + + public void testGetRawDictWorks() throws IOException, UnsupportedFormatException { + // Create a thrice-compressed dictionary file. + final FusionDictionary dict = new FusionDictionary(new Node(), + new DictionaryOptions(new HashMap(), + false /* germanUmlautProcessing */, false /* frenchLigatureProcessing */)); + dict.add("foo", TEST_FREQ, null, false /* isNotAWord */); + dict.add("fta", 1, null, false /* isNotAWord */); + dict.add("ftb", 1, null, false /* isNotAWord */); + dict.add("bar", 1, null, false /* isNotAWord */); + dict.add("fool", 1, null, false /* isNotAWord */); + + final File dst = File.createTempFile("testGetRawDict", ".tmp"); + final OutputStream out = Compress.getCompressedStream( + Compress.getCompressedStream( + Compress.getCompressedStream( + new BufferedOutputStream(new FileOutputStream(dst))))); + + BinaryDictInputOutput.writeDictionaryBinary(out, dict, new FormatOptions(2, false)); + + // Test for an actually compressed dictionary and its contents + final BinaryDictOffdeviceUtils.DecoderChainSpec decodeSpec = + BinaryDictOffdeviceUtils.getRawBinaryDictionaryOrNull(dst); + for (final String step : decodeSpec.mDecoderSpec) { + assertEquals("Wrong decode spec", BinaryDictOffdeviceUtils.COMPRESSION, step); + } + assertEquals("Wrong decode spec", 3, decodeSpec.mDecoderSpec.size()); + final FileInputStream inStream = new FileInputStream(decodeSpec.mFile); + final ByteBuffer buffer = inStream.getChannel().map( + FileChannel.MapMode.READ_ONLY, 0, decodeSpec.mFile.length()); + final FusionDictionary resultDict = BinaryDictInputOutput.readDictionaryBinary( + new BinaryDictInputOutput.ByteBufferWrapper(buffer), + null /* dict : an optional dictionary to add words to, or null */); + assertEquals("Dictionary can't be read back correctly", + resultDict.findWordInTree(resultDict.mRoot, "foo").getFrequency(), TEST_FREQ); + } + + public void testGetRawDictFails() throws IOException { + // Randomly create some 4k file containing garbage + final File dst = File.createTempFile("testGetRawDict", ".tmp"); + final OutputStream out = new BufferedOutputStream(new FileOutputStream(dst)); + for (int i = 0; i < 1024; ++i) { + out.write(0x12345678); + } + out.close(); + + // Test that a random data file actually fails + assertNull("Wrongly identified data file", + BinaryDictOffdeviceUtils.getRawBinaryDictionaryOrNull(dst)); + + final File gzDst = File.createTempFile("testGetRawDict", ".tmp"); + final OutputStream gzOut = + Compress.getCompressedStream(new BufferedOutputStream(new FileOutputStream(gzDst))); + for (int i = 0; i < 1024; ++i) { + gzOut.write(0x12345678); + } + gzOut.close(); + + // Test that a compressed random data file actually fails + assertNull("Wrongly identified data file", + BinaryDictOffdeviceUtils.getRawBinaryDictionaryOrNull(gzDst)); + } +} diff --git a/tools/dicttool/tests/etc/test-dicttool.sh b/tools/dicttool/tests/etc/test-dicttool.sh index 1283be21a..0f3ed6d62 100755 --- a/tools/dicttool/tests/etc/test-dicttool.sh +++ b/tools/dicttool/tests/etc/test-dicttool.sh @@ -14,3 +14,4 @@ # limitations under the License. java -classpath ${ANDROID_HOST_OUT}/framework/junit.jar:${ANDROID_HOST_OUT}/framework/dicttool_aosp.jar junit.textui.TestRunner com.android.inputmethod.latin.makedict.BinaryDictInputOutputTest +java -classpath ${ANDROID_HOST_OUT}/framework/junit.jar:${ANDROID_HOST_OUT}/framework/dicttool_aosp.jar junit.textui.TestRunner com.android.inputmethod.latin.dicttool.BinaryDictOffdeviceUtilsTests -- cgit v1.2.3-83-g751a From 47cac57e4593f47e753410e4199e84e458d6de6f Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Thu, 25 Oct 2012 18:15:42 +0900 Subject: Finish up the "info" command in dicttool. (A6) Bug: 7388857 Change-Id: I704f12a6be76ce1644ec5e8dd3b667f112e9c04a --- .../inputmethod/latin/makedict/FormatSpec.java | 2 ++ .../latin/makedict/FusionDictionary.java | 36 +++++++++++++++++++-- .../latin/dicttool/CombinedInputOutput.java | 6 ++-- .../android/inputmethod/latin/dicttool/Info.java | 37 ++++++++++++++++++++-- 4 files changed, 75 insertions(+), 6 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index e88a4aebf..705f66414 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -224,6 +224,8 @@ public final class FormatSpec { static final int MAX_TERMINAL_FREQUENCY = 255; static final int MAX_BIGRAM_FREQUENCY = 15; + public static final int SHORTCUT_WHITELIST_FREQUENCY = 15; + // This option needs to be the same numeric value as the one in binary_format.h. static final int NOT_VALID_WORD = -99; static final int SIGNED_CHILDREN_ADDRESS_SIZE = 3; diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java index 44537986b..4abed9f7f 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java +++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java @@ -22,6 +22,7 @@ import com.android.inputmethod.latin.Constants; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; @@ -255,8 +256,6 @@ public final class FusionDictionary implements Iterable { /** * Options global to the dictionary. - * - * There are no options at the moment, so this class is empty. */ public static final class DictionaryOptions { public final boolean mGermanUmlautProcessing; @@ -268,6 +267,39 @@ public final class FusionDictionary implements Iterable { mGermanUmlautProcessing = germanUmlautProcessing; mFrenchLigatureProcessing = frenchLigatureProcessing; } + @Override + public String toString() { // Convenience method + return toString(0); + } + public String toString(final int indentCount) { + final StringBuilder indent = new StringBuilder(); + for (int i = 0; i < indentCount; ++i) { + indent.append(" "); + } + final StringBuilder s = new StringBuilder(); + for (final String optionKey : mAttributes.keySet()) { + s.append(indent); + s.append(optionKey); + s.append(" = "); + if ("date".equals(optionKey)) { + // Date needs a number of milliseconds, but the dictionary contains seconds + s.append(new Date( + 1000 * Long.parseLong(mAttributes.get(optionKey))).toString()); + } else { + s.append(mAttributes.get(optionKey)); + } + s.append("\n"); + } + if (mGermanUmlautProcessing) { + s.append(indent); + s.append("Needs German umlaut processing\n"); + } + if (mFrenchLigatureProcessing) { + s.append(indent); + s.append("Needs French ligature processing\n"); + } + return s.toString(); + } } public final DictionaryOptions mOptions; diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java index c17667536..cd04d18bb 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java @@ -16,6 +16,7 @@ package com.android.inputmethod.latin.dicttool; +import com.android.inputmethod.latin.makedict.FormatSpec; import com.android.inputmethod.latin.makedict.FusionDictionary; import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions; import com.android.inputmethod.latin.makedict.FusionDictionary.Node; @@ -150,8 +151,9 @@ public class CombinedInputOutput { if (SHORTCUT_TAG.equals(params[0])) { shortcut = params[1]; } else if (FREQUENCY_TAG.equals(params[0])) { - shortcutFreq = - WHITELIST_TAG.equals(params[1]) ? 15 : Integer.parseInt(params[1]); + shortcutFreq = WHITELIST_TAG.equals(params[1]) + ? FormatSpec.SHORTCUT_WHITELIST_FREQUENCY + : Integer.parseInt(params[1]); } } if (null != shortcut) { diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java index bafde627d..be4b2b881 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java @@ -18,8 +18,11 @@ package com.android.inputmethod.latin.dicttool; import com.android.inputmethod.latin.dicttool.BinaryDictOffdeviceUtils.DecoderChainSpec; import com.android.inputmethod.latin.makedict.BinaryDictInputOutput; +import com.android.inputmethod.latin.makedict.FormatSpec; import com.android.inputmethod.latin.makedict.FusionDictionary; +import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; import com.android.inputmethod.latin.makedict.UnsupportedFormatException; +import com.android.inputmethod.latin.makedict.Word; import org.xml.sax.SAXException; @@ -38,8 +41,9 @@ public class Info extends Dicttool.Command { public Info() { } + @Override public String getHelp() { - return "info : prints various information about a dictionary file"; + return COMMAND + ": prints various information about a dictionary file"; } private static void crash(final String filename, final Exception e) { @@ -72,6 +76,7 @@ public class Info extends Dicttool.Command { FileChannel.MapMode.READ_ONLY, 0, decodedSpec.mFile.length()); System.out.println("Format : Binary dictionary format"); System.out.println("Packaging : " + decodedSpec.describeChain()); + System.out.println("Uncompressed size : " + decodedSpec.mFile.length()); return BinaryDictInputOutput.readDictionaryBinary( new BinaryDictInputOutput.ByteBufferWrapper(buffer), null); } @@ -87,12 +92,40 @@ public class Info extends Dicttool.Command { return null; } + private static void showInfo(final FusionDictionary dict) { + System.out.println("Header attributes :"); + System.out.print(dict.mOptions.toString(2)); + int wordCount = 0; + int bigramCount = 0; + int shortcutCount = 0; + int whitelistCount = 0; + for (final Word w : dict) { + ++wordCount; + if (null != w.mBigrams) { + bigramCount += w.mBigrams.size(); + } + if (null != w.mShortcutTargets) { + shortcutCount += w.mShortcutTargets.size(); + for (WeightedString shortcutTarget : w.mShortcutTargets) { + if (FormatSpec.SHORTCUT_WHITELIST_FREQUENCY == shortcutTarget.mFrequency) { + ++whitelistCount; + } + } + } + } + System.out.println("Words in the dictionary : " + wordCount); + System.out.println("Bigram count : " + bigramCount); + System.out.println("Shortcuts : " + shortcutCount + " (out of which " + whitelistCount + + " whitelist entries)"); + } + + @Override public void run() { - // TODO: implement this if (mArgs.length < 1) { throw new RuntimeException("Not enough arguments for command " + COMMAND); } final String filename = mArgs[0]; final FusionDictionary dict = getDictionary(filename); + showInfo(dict); } } -- cgit v1.2.3-83-g751a From 60dea36dafc4a567b948b5175bcca776b08fdfad Mon Sep 17 00:00:00 2001 From: Satoshi Kataoka Date: Thu, 25 Oct 2012 14:48:12 +0900 Subject: Assuming that NO_EXTRACT_UI mode is NO_FULSCREEN Bug: 7393485 Bug: 7272829 Change-Id: I873e8d99486c734e76484526631a90fc55e91c86 --- java/src/com/android/inputmethod/latin/LatinIME.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 1ade3c422..8ac0cd4ca 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1063,7 +1063,16 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // Reread resource value here, because this method is called by framework anytime as needed. final boolean isFullscreenModeAllowed = mCurrentSettings.isFullscreenModeAllowed(getResources()); - return super.onEvaluateFullscreenMode() && isFullscreenModeAllowed; + if (super.onEvaluateFullscreenMode() && isFullscreenModeAllowed) { + // TODO: Remove this hack. Actually we should not really assume NO_EXTRACT_UI + // implies NO_FULLSCREEN. However, the framework mistakenly does. i.e. NO_EXTRACT_UI + // without NO_FULLSCREEN doesn't work as expected. Because of this we need this + // hack for now. Let's get rid of this once the framework gets fixed. + final EditorInfo ei = getCurrentInputEditorInfo(); + return !(ei != null && ((ei.imeOptions & EditorInfo.IME_FLAG_NO_EXTRACT_UI) != 0)); + } else { + return false; + } } @Override -- cgit v1.2.3-83-g751a From a23e3330798a3ade6d2f4f5a94b71746feb1b948 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Mon, 29 Oct 2012 11:09:30 +0900 Subject: Implement the word-level diff (A9) Bug: 7388857 Change-Id: I4c4560d4f4b579936a44cdf409a4c27300b65610 --- .../latin/makedict/FusionDictionary.java | 25 +++++- .../android/inputmethod/latin/dicttool/Diff.java | 90 +++++++++++++++++++--- 2 files changed, 103 insertions(+), 12 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java index 4abed9f7f..93db8e833 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java +++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java @@ -143,11 +143,34 @@ public final class FusionDictionary implements Iterable { return NOT_A_TERMINAL != mFrequency; } - @UsedForTesting public int getFrequency() { return mFrequency; } + public boolean getIsNotAWord() { + return mIsNotAWord; + } + + public boolean getIsBlacklistEntry() { + return mIsBlacklistEntry; + } + + public ArrayList getShortcutTargets() { + // We don't want write permission to escape outside the package, so we return a copy + if (null == mShortcutTargets) return null; + final ArrayList copyOfShortcutTargets = new ArrayList(); + copyOfShortcutTargets.addAll(mShortcutTargets); + return copyOfShortcutTargets; + } + + public ArrayList getBigrams() { + // We don't want write permission to escape outside the package, so we return a copy + if (null == mBigrams) return null; + final ArrayList copyOfBigrams = new ArrayList(); + copyOfBigrams.addAll(mBigrams); + return copyOfBigrams; + } + public boolean hasSeveralChars() { assert(mChars.length > 0); return 1 < mChars.length; diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java index 60ba9383d..ad5f4e2b2 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java @@ -17,8 +17,13 @@ package com.android.inputmethod.latin.dicttool; import com.android.inputmethod.latin.makedict.FusionDictionary; +import com.android.inputmethod.latin.makedict.FusionDictionary.CharGroup; +import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; +import com.android.inputmethod.latin.makedict.Word; import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashMap; public class Diff extends Dicttool.Command { public static final String COMMAND = "diff"; @@ -57,22 +62,20 @@ public class Diff extends Dicttool.Command { System.out.println("Header :"); diffHeaders(dict0, dict1); if (languageDiffers(dict0, dict1)) { - // diffHeaders returns whether the language is different. If it is, we should bail - // to avoid flooding the output with thousands of useless word-level diffs. + // We only check for the language here. The rationale is that one may meaningfully + // diff a en_US with a en_GB dictionary, but someone who diffs a de dict with a + // pt_BR dict is almost certainly only interested in header-level diff, and the word + // diff would be very large, meaningless, and annoying. return; } System.out.println("Body :"); } - // TODO: implement the word-level diff + diffWords(dict0, dict1); } private static boolean languageDiffers(final FusionDictionary dict0, final FusionDictionary dict1) { // If either of the dictionaries have no locale, assume it's okay - // We only check for the language here. The rationale is that one may meaningfully diff - // a en_US with a en_GB dictionary, but someone who diffs a de dict with a pt_BR dict - // is almost certainly only interested in header-level diff, and the word diff would be very - // large, meaningless, and annoying. if (null == dict0.mOptions.mAttributes.get("locale")) return true; if (null == dict1.mOptions.mAttributes.get("locale")) return true; final String dict0Lang = dict0.mOptions.mAttributes.get("locale").split("_", 3)[0]; @@ -91,6 +94,8 @@ public class Diff extends Dicttool.Command { + dict0.mOptions.mGermanUmlautProcessing + " <=> " + dict1.mOptions.mGermanUmlautProcessing); } + final HashMap options1 = + (HashMap)dict1.mOptions.mAttributes.clone(); for (final String optionKey : dict0.mOptions.mAttributes.keySet()) { if (!dict0.mOptions.mAttributes.get(optionKey).equals( dict1.mOptions.mAttributes.get(optionKey))) { @@ -98,11 +103,74 @@ public class Diff extends Dicttool.Command { + dict0.mOptions.mAttributes.get(optionKey) + " <=> " + dict1.mOptions.mAttributes.get(optionKey)); } - dict1.mOptions.mAttributes.remove(optionKey); + options1.remove(optionKey); } - for (final String optionKey : dict1.mOptions.mAttributes.keySet()) { - System.out.println(" " + optionKey + " : null <=> " - + dict1.mOptions.mAttributes.get(optionKey)); + for (final String optionKey : options1.keySet()) { + System.out.println(" " + optionKey + " : null <=> " + options1.get(optionKey)); + } + } + + private static void diffWords(final FusionDictionary dict0, final FusionDictionary dict1) { + for (final Word word0 : dict0) { + final CharGroup word1 = dict1.findWordInTree(dict1.mRoot, word0.mWord); + if (null == word1) { + // This word is not in dict1 + System.out.println("Deleted: " + word0.mWord + " " + word0.mFrequency); + } else { + // We found the word. Compare frequencies, shortcuts, bigrams + if (word0.mFrequency != word1.getFrequency()) { + System.out.println("Freq changed: " + word0.mWord + " " + word0.mFrequency + + " -> " + word1.getFrequency()); + } + if (word0.mIsNotAWord != word1.getIsNotAWord()) { + System.out.println("Not a word: " + word0.mWord + " " + word0.mIsNotAWord + + " -> " + word1.getIsNotAWord()); + } + if (word0.mIsBlacklistEntry != word1.getIsBlacklistEntry()) { + System.out.println("Blacklist: " + word0.mWord + " " + word0.mIsBlacklistEntry + + " -> " + word1.getIsBlacklistEntry()); + } + diffAttributes(word0.mWord, word0.mBigrams, word1.getBigrams()); + diffAttributes(word0.mWord, word0.mShortcutTargets, word1.getShortcutTargets()); + } + } + } + + private static void diffAttributes(final String word, final ArrayList list0, + final ArrayList list1) { + if (null == list1) { + if (null == list0) return; + for (final WeightedString attribute0 : list0) { + System.out.println("Bigram removed: " + word + " " + attribute0.mWord + " " + + attribute0.mFrequency); + } + } else if (null != list0) { + for (final WeightedString attribute0 : list0) { + // The following tests with #equals(). The WeightedString#equals() method returns + // true if both the string and the frequency are the same. + if (!list1.contains(attribute0)) { + // Search for a word with the same string but a different frequency + for (final WeightedString attribute1 : list1) { + if (attribute0.mWord.equals(attribute1.mWord)) { + System.out.println("Bigram freq changed: " + word + " " + + attribute0.mWord + " " + attribute0.mFrequency + " -> " + + attribute1.mFrequency); + list1.remove(attribute1); + break; + } + // We come here if we haven't found any matching string. + System.out.println("Bigram removed: " + word + " " + attribute0.mWord); + } + } else { + list1.remove(attribute0); + } + } + } + // We removed any matching word that we found, so now list1 only contains words that + // are not included in list0. + for (final WeightedString attribute1 : list1) { + System.out.println("Bigram added: " + word + " " + attribute1.mWord + " " + + attribute1.mFrequency); } } } -- cgit v1.2.3-83-g751a From f41389a74b02a01f7383b1a872db5fa65e81fa1e Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Mon, 29 Oct 2012 14:24:16 +0900 Subject: Remove warnings Thanks Eclipse Change-Id: I88e3979ed22be5d8be5a5accdde417c6b1a8bf2d --- .../inputmethod/latin/makedict/BinaryDictIOUtils.java | 1 + .../inputmethod/latin/makedict/BinaryDictInputOutput.java | 12 ++++-------- .../android/inputmethod/latin/makedict/FusionDictionary.java | 8 +++----- .../inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java | 2 -- .../src/com/android/inputmethod/latin/dicttool/Diff.java | 4 ++-- .../src/com/android/inputmethod/latin/dicttool/Info.java | 2 +- 6 files changed, 11 insertions(+), 18 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 05f2d933c..ee0e9cd7e 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -565,6 +565,7 @@ public final class BinaryDictIOUtils { return size; } + @SuppressWarnings("unused") private static void updateForwardLink(final FusionDictionaryBufferInterface buffer, final int nodeOriginAddress, final int newNodeAddress, final FormatOptions formatOptions) { diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 031306e1d..d1a3c7b0a 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -77,12 +77,12 @@ public final class BinaryDictInputOutput { @Override public int readUnsignedByte() { - return ((int)mBuffer.get()) & 0xFF; + return mBuffer.get() & 0xFF; } @Override public int readUnsignedShort() { - return ((int)mBuffer.getShort()) & 0xFFFF; + return mBuffer.getShort() & 0xFFFF; } @Override @@ -474,11 +474,8 @@ public final class BinaryDictInputOutput { } } - private static final int SINT8_MAX = 0x7F; - private static final int SINT16_MAX = 0x7FFF; private static final int SINT24_MAX = 0x7FFFFF; private static final int MSB8 = 0x80; - private static final int MSB16 = 0x8000; private static final int MSB24 = 0x800000; // End utility methods. @@ -1711,7 +1708,7 @@ public final class BinaryDictInputOutput { * * Concretely this only tests the magic number. * - * @param filename The name of the file to test. + * @param file The file to test. * @return true if it's a binary dictionary, false otherwise */ public static boolean isBinaryDictionary(final File file) { @@ -1751,8 +1748,7 @@ public final class BinaryDictInputOutput { final int bigramFrequency) { final float stepSize = (FormatSpec.MAX_TERMINAL_FREQUENCY - unigramFrequency) / (1.5f + FormatSpec.MAX_BIGRAM_FREQUENCY); - final float resultFreqFloat = (float)unigramFrequency - + stepSize * (bigramFrequency + 1.0f); + final float resultFreqFloat = unigramFrequency + stepSize * (bigramFrequency + 1.0f); return (int)resultFreqFloat; } } diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java index 93db8e833..c588824fe 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java +++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java @@ -16,7 +16,6 @@ package com.android.inputmethod.latin.makedict; -import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.Constants; import java.util.ArrayList; @@ -158,16 +157,15 @@ public final class FusionDictionary implements Iterable { public ArrayList getShortcutTargets() { // We don't want write permission to escape outside the package, so we return a copy if (null == mShortcutTargets) return null; - final ArrayList copyOfShortcutTargets = new ArrayList(); - copyOfShortcutTargets.addAll(mShortcutTargets); + final ArrayList copyOfShortcutTargets = + new ArrayList(mShortcutTargets); return copyOfShortcutTargets; } public ArrayList getBigrams() { // We don't want write permission to escape outside the package, so we return a copy if (null == mBigrams) return null; - final ArrayList copyOfBigrams = new ArrayList(); - copyOfBigrams.addAll(mBigrams); + final ArrayList copyOfBigrams = new ArrayList(mBigrams); return copyOfBigrams; } diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java index 4573fa6f7..0803b08d5 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java @@ -17,7 +17,6 @@ package com.android.inputmethod.latin.dicttool; import com.android.inputmethod.latin.makedict.BinaryDictInputOutput; -import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.ByteBufferWrapper; import com.android.inputmethod.latin.makedict.FusionDictionary; import com.android.inputmethod.latin.makedict.UnsupportedFormatException; @@ -33,7 +32,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; -import java.nio.channels.FileChannel.MapMode; import java.util.ArrayList; import javax.xml.parsers.ParserConfigurationException; diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java index ad5f4e2b2..9548f2509 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java @@ -95,7 +95,7 @@ public class Diff extends Dicttool.Command { + dict1.mOptions.mGermanUmlautProcessing); } final HashMap options1 = - (HashMap)dict1.mOptions.mAttributes.clone(); + new HashMap(dict1.mOptions.mAttributes); for (final String optionKey : dict0.mOptions.mAttributes.keySet()) { if (!dict0.mOptions.mAttributes.get(optionKey).equals( dict1.mOptions.mAttributes.get(optionKey))) { @@ -112,7 +112,7 @@ public class Diff extends Dicttool.Command { private static void diffWords(final FusionDictionary dict0, final FusionDictionary dict1) { for (final Word word0 : dict0) { - final CharGroup word1 = dict1.findWordInTree(dict1.mRoot, word0.mWord); + final CharGroup word1 = FusionDictionary.findWordInTree(dict1.mRoot, word0.mWord); if (null == word1) { // This word is not in dict1 System.out.println("Deleted: " + word0.mWord + " " + word0.mFrequency); diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java index 6f1c020f2..7f25818fb 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java @@ -63,7 +63,7 @@ public class Info extends Dicttool.Command { } private static void showWordInfo(final FusionDictionary dict, final String word) { - final CharGroup group = dict.findWordInTree(dict.mRoot, word); + final CharGroup group = FusionDictionary.findWordInTree(dict.mRoot, word); if (null == group) { System.out.println(word + " is not in the dictionary"); return; -- cgit v1.2.3-83-g751a From 240871ecafde7834ebb4270cd7758fc904a5f3a7 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Mon, 29 Oct 2012 14:46:34 +0900 Subject: Move code point constants from Keyboard to Constants class Change-Id: Iee01d4d2b916d0b584531104ac865ae6e6370a3d --- .../accessibility/KeyCodeDescriptionMapper.java | 33 +++++---- java/src/com/android/inputmethod/keyboard/Key.java | 11 +-- .../android/inputmethod/keyboard/KeyDetector.java | 4 +- .../com/android/inputmethod/keyboard/Keyboard.java | 71 +------------------ .../inputmethod/keyboard/MainKeyboardView.java | 16 ++--- .../inputmethod/keyboard/PointerTracker.java | 19 ++--- .../inputmethod/keyboard/ProximityInfo.java | 7 +- .../keyboard/internal/KeySpecParser.java | 13 ++-- .../keyboard/internal/KeyboardCodesSet.java | 32 ++++----- .../keyboard/internal/KeyboardParams.java | 4 +- .../keyboard/internal/KeyboardState.java | 33 +++++---- .../inputmethod/keyboard/internal/MoreKeySpec.java | 10 +-- .../latin/AudioAndHapticFeedbackManager.java | 7 +- .../com/android/inputmethod/latin/Constants.java | 70 +++++++++++++++++++ .../latin/ContactsBinaryDictionary.java | 4 +- .../inputmethod/latin/ExpandableDictionary.java | 5 +- .../com/android/inputmethod/latin/LatinIME.java | 80 +++++++++++----------- .../inputmethod/latin/RichInputConnection.java | 7 +- .../com/android/inputmethod/latin/StringUtils.java | 19 +++-- .../src/com/android/inputmethod/latin/Suggest.java | 3 +- .../android/inputmethod/latin/WordComposer.java | 6 +- .../inputmethod/research/ResearchLogger.java | 8 +-- .../android/inputmethod/research/Statistics.java | 4 +- .../keyboard/internal/KeySpecParserTests.java | 10 +-- .../keyboard/internal/KeyboardStateTestsBase.java | 2 +- .../keyboard/internal/MockKeyboardSwitcher.java | 57 ++++++++------- .../inputmethod/latin/BlueUnderlineTests.java | 8 +-- .../android/inputmethod/latin/InputLogicTests.java | 26 ++++--- 28 files changed, 282 insertions(+), 287 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java index 32618ad85..b87ae3a15 100644 --- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java +++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java @@ -26,6 +26,7 @@ import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardId; import com.android.inputmethod.latin.CollectionUtils; +import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; import java.util.HashMap; @@ -61,17 +62,19 @@ public final class KeyCodeDescriptionMapper { mKeyLabelMap.put(":-)", R.string.spoken_description_smiley); // Special non-character codes defined in Keyboard - mKeyCodeMap.put(Keyboard.CODE_SPACE, R.string.spoken_description_space); - mKeyCodeMap.put(Keyboard.CODE_DELETE, R.string.spoken_description_delete); - mKeyCodeMap.put(Keyboard.CODE_ENTER, R.string.spoken_description_return); - mKeyCodeMap.put(Keyboard.CODE_SETTINGS, R.string.spoken_description_settings); - mKeyCodeMap.put(Keyboard.CODE_SHIFT, R.string.spoken_description_shift); - mKeyCodeMap.put(Keyboard.CODE_SHORTCUT, R.string.spoken_description_mic); - mKeyCodeMap.put(Keyboard.CODE_SWITCH_ALPHA_SYMBOL, R.string.spoken_description_to_symbol); - mKeyCodeMap.put(Keyboard.CODE_TAB, R.string.spoken_description_tab); - mKeyCodeMap.put(Keyboard.CODE_LANGUAGE_SWITCH, R.string.spoken_description_language_switch); - mKeyCodeMap.put(Keyboard.CODE_ACTION_NEXT, R.string.spoken_description_action_next); - mKeyCodeMap.put(Keyboard.CODE_ACTION_PREVIOUS, R.string.spoken_description_action_previous); + mKeyCodeMap.put(Constants.CODE_SPACE, R.string.spoken_description_space); + mKeyCodeMap.put(Constants.CODE_DELETE, R.string.spoken_description_delete); + mKeyCodeMap.put(Constants.CODE_ENTER, R.string.spoken_description_return); + mKeyCodeMap.put(Constants.CODE_SETTINGS, R.string.spoken_description_settings); + mKeyCodeMap.put(Constants.CODE_SHIFT, R.string.spoken_description_shift); + mKeyCodeMap.put(Constants.CODE_SHORTCUT, R.string.spoken_description_mic); + mKeyCodeMap.put(Constants.CODE_SWITCH_ALPHA_SYMBOL, R.string.spoken_description_to_symbol); + mKeyCodeMap.put(Constants.CODE_TAB, R.string.spoken_description_tab); + mKeyCodeMap.put(Constants.CODE_LANGUAGE_SWITCH, + R.string.spoken_description_language_switch); + mKeyCodeMap.put(Constants.CODE_ACTION_NEXT, R.string.spoken_description_action_next); + mKeyCodeMap.put(Constants.CODE_ACTION_PREVIOUS, + R.string.spoken_description_action_previous); } /** @@ -97,17 +100,17 @@ public final class KeyCodeDescriptionMapper { boolean shouldObscure) { final int code = key.mCode; - if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { + if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) { final String description = getDescriptionForSwitchAlphaSymbol(context, keyboard); if (description != null) return description; } - if (code == Keyboard.CODE_SHIFT) { + if (code == Constants.CODE_SHIFT) { return getDescriptionForShiftKey(context, keyboard); } - if (code == Keyboard.CODE_ACTION_ENTER) { + if (code == Constants.CODE_ACTION_ENTER) { return getDescriptionForActionKey(context, keyboard, key); } @@ -121,7 +124,7 @@ public final class KeyCodeDescriptionMapper { } // Just attempt to speak the description. - if (key.mCode != Keyboard.CODE_UNSPECIFIED) { + if (key.mCode != Constants.CODE_UNSPECIFIED) { return getDescriptionForKeyCode(context, keyboard, key, shouldObscure); } diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index 30812e8c3..7346a9c38 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -16,11 +16,11 @@ package com.android.inputmethod.keyboard; -import static com.android.inputmethod.keyboard.Keyboard.CODE_OUTPUT_TEXT; -import static com.android.inputmethod.keyboard.Keyboard.CODE_SHIFT; -import static com.android.inputmethod.keyboard.Keyboard.CODE_SWITCH_ALPHA_SYMBOL; -import static com.android.inputmethod.keyboard.Keyboard.CODE_UNSPECIFIED; import static com.android.inputmethod.keyboard.internal.KeyboardIconsSet.ICON_UNDEFINED; +import static com.android.inputmethod.latin.Constants.CODE_OUTPUT_TEXT; +import static com.android.inputmethod.latin.Constants.CODE_SHIFT; +import static com.android.inputmethod.latin.Constants.CODE_SWITCH_ALPHA_SYMBOL; +import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED; import android.content.res.Resources; import android.content.res.TypedArray; @@ -39,6 +39,7 @@ import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.internal.KeyboardParams; import com.android.inputmethod.keyboard.internal.KeyboardRow; import com.android.inputmethod.keyboard.internal.MoreKeySpec; +import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.ResourceUtils; import com.android.inputmethod.latin.StringUtils; @@ -453,7 +454,7 @@ public class Key implements Comparable { label = "/" + mLabel; } return String.format("%s%s %d,%d %dx%d %s/%s/%s", - Keyboard.printableCode(mCode), label, mX, mY, mWidth, mHeight, mHintLabel, + Constants.printableCode(mCode), label, mX, mY, mWidth, mHeight, mHintLabel, KeyboardIconsSet.getIconName(mIconId), backgroundName(mBackgroundType)); } diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java index aa683c1d7..0a91284d0 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java +++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java @@ -118,7 +118,7 @@ public class KeyDetector { } public static String printableCode(Key key) { - return key != null ? Keyboard.printableCode(key.mCode) : "none"; + return key != null ? Constants.printableCode(key.mCode) : "none"; } public static String printableCodes(int[] codes) { @@ -127,7 +127,7 @@ public class KeyDetector { for (final int code : codes) { if (code == Constants.NOT_A_CODE) break; if (addDelimiter) sb.append(", "); - sb.append(Keyboard.printableCode(code)); + sb.append(Constants.printableCode(code)); addDelimiter = true; } return "[" + sb + "]"; diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index b7c7f415d..dd2e3d392 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -16,13 +16,13 @@ package com.android.inputmethod.keyboard; -import android.util.Log; import android.util.SparseArray; import com.android.inputmethod.keyboard.internal.KeyVisualAttributes; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.internal.KeyboardParams; import com.android.inputmethod.latin.CollectionUtils; +import com.android.inputmethod.latin.Constants; @@ -45,46 +45,6 @@ import com.android.inputmethod.latin.CollectionUtils; * */ public class Keyboard { - private static final String TAG = Keyboard.class.getSimpleName(); - - /** Some common keys code. Must be positive. - * These should be aligned with values/keycodes.xml - */ - public static final int CODE_ENTER = '\n'; - public static final int CODE_TAB = '\t'; - public static final int CODE_SPACE = ' '; - public static final int CODE_PERIOD = '.'; - public static final int CODE_DASH = '-'; - public static final int CODE_SINGLE_QUOTE = '\''; - public static final int CODE_DOUBLE_QUOTE = '"'; - public static final int CODE_QUESTION_MARK = '?'; - public static final int CODE_EXCLAMATION_MARK = '!'; - // TODO: Check how this should work for right-to-left languages. It seems to stand - // that for rtl languages, a closing parenthesis is a left parenthesis. Is this - // managed by the font? Or is it a different char? - public static final int CODE_CLOSING_PARENTHESIS = ')'; - public static final int CODE_CLOSING_SQUARE_BRACKET = ']'; - public static final int CODE_CLOSING_CURLY_BRACKET = '}'; - public static final int CODE_CLOSING_ANGLE_BRACKET = '>'; - - /** Special keys code. Must be negative. - * These should be aligned with KeyboardCodesSet.ID_TO_NAME[], - * KeyboardCodesSet.DEFAULT[] and KeyboardCodesSet.RTL[] - */ - public static final int CODE_SHIFT = -1; - public static final int CODE_SWITCH_ALPHA_SYMBOL = -2; - public static final int CODE_OUTPUT_TEXT = -3; - public static final int CODE_DELETE = -4; - public static final int CODE_SETTINGS = -5; - public static final int CODE_SHORTCUT = -6; - public static final int CODE_ACTION_ENTER = -7; - public static final int CODE_ACTION_NEXT = -8; - public static final int CODE_ACTION_PREVIOUS = -9; - public static final int CODE_LANGUAGE_SWITCH = -10; - public static final int CODE_RESEARCH = -11; - // Code value representing the code is not specified. - public static final int CODE_UNSPECIFIED = -12; - public final KeyboardId mId; public final int mThemeId; @@ -163,7 +123,7 @@ public class Keyboard { } public Key getKey(final int code) { - if (code == CODE_UNSPECIFIED) { + if (code == Constants.CODE_UNSPECIFIED) { return null; } synchronized (mKeyCache) { @@ -197,10 +157,6 @@ public class Keyboard { return false; } - public static boolean isLetterCode(final int code) { - return code >= CODE_SPACE; - } - @Override public String toString() { return mId.toString(); @@ -219,27 +175,4 @@ public class Keyboard { final int adjustedY = Math.max(0, Math.min(y, mOccupiedHeight - 1)); return mProximityInfo.getNearestKeys(adjustedX, adjustedY); } - - public static String printableCode(final int code) { - switch (code) { - case CODE_SHIFT: return "shift"; - case CODE_SWITCH_ALPHA_SYMBOL: return "symbol"; - case CODE_OUTPUT_TEXT: return "text"; - case CODE_DELETE: return "delete"; - case CODE_SETTINGS: return "settings"; - case CODE_SHORTCUT: return "shortcut"; - case CODE_ACTION_ENTER: return "actionEnter"; - case CODE_ACTION_NEXT: return "actionNext"; - case CODE_ACTION_PREVIOUS: return "actionPrevious"; - case CODE_LANGUAGE_SWITCH: return "languageSwitch"; - case CODE_UNSPECIFIED: return "unspec"; - case CODE_TAB: return "tab"; - case CODE_ENTER: return "enter"; - default: - if (code <= 0) Log.w(TAG, "Unknown non-positive key code=" + code); - if (code < CODE_SPACE) return String.format("'\\u%02x'", code); - if (code < 0x100) return String.format("'%c'", code); - return String.format("'\\u%04x'", code); - } - } } diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index 5b6820fa6..4efc526bf 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -227,7 +227,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack cancelLongPressTimer(); final int delay; switch (code) { - case Keyboard.CODE_SHIFT: + case Constants.CODE_SHIFT: delay = mLongPressShiftKeyTimeout; break; default: @@ -248,7 +248,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack final Key key = tracker.getKey(); final int delay; switch (key.mCode) { - case Keyboard.CODE_SHIFT: + case Constants.CODE_SHIFT: delay = mLongPressShiftKeyTimeout; break; default: @@ -305,7 +305,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack // When user hits the space or the enter key, just cancel the while-typing timer. final int typedCode = typedKey.mCode; - if (typedCode == Keyboard.CODE_SPACE || typedCode == Keyboard.CODE_ENTER) { + if (typedCode == Constants.CODE_SPACE || typedCode == Constants.CODE_ENTER) { startWhileTypingFadeinAnimation(keyboardView); return; } @@ -487,7 +487,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack mTouchScreenRegulator.setKeyboard(keyboard); mMoreKeysPanelCache.clear(); - mSpaceKey = keyboard.getKey(Keyboard.CODE_SPACE); + mSpaceKey = keyboard.getKey(Constants.CODE_SPACE); mSpaceIcon = (mSpaceKey != null) ? mSpaceKey.getIcon(keyboard.mIconsSet, Constants.Color.ALPHA_OPAQUE) : null; final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap; @@ -604,7 +604,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack KeyboardSwitcher.getInstance().hapticAndAudioFeedback(primaryCode); return true; } - if (primaryCode == Keyboard.CODE_SPACE || primaryCode == Keyboard.CODE_LANGUAGE_SWITCH) { + if (primaryCode == Constants.CODE_SPACE || primaryCode == Constants.CODE_LANGUAGE_SWITCH) { // Long pressing the space key invokes IME switcher dialog. if (invokeCustomRequest(LatinIME.CODE_SHOW_INPUT_METHOD_PICKER)) { tracker.onLongPressed(); @@ -875,7 +875,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack public void updateShortcutKey(final boolean available) { final Keyboard keyboard = getKeyboard(); if (keyboard == null) return; - final Key shortcutKey = keyboard.getKey(Keyboard.CODE_SHORTCUT); + final Key shortcutKey = keyboard.getKey(Constants.CODE_SHORTCUT); if (shortcutKey == null) return; shortcutKey.setEnabled(available); invalidateKey(shortcutKey); @@ -924,13 +924,13 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack if (key.altCodeWhileTyping() && key.isEnabled()) { params.mAnimAlpha = mAltCodeKeyWhileTypingAnimAlpha; } - if (key.mCode == Keyboard.CODE_SPACE) { + if (key.mCode == Constants.CODE_SPACE) { drawSpacebar(key, canvas, paint); // Whether space key needs to show the "..." popup hint for special purposes if (key.isLongPressEnabled() && mHasMultipleEnabledIMEsOrSubtypes) { drawKeyPopupHint(key, canvas, paint, params); } - } else if (key.mCode == Keyboard.CODE_LANGUAGE_SWITCH) { + } else if (key.mCode == Constants.CODE_LANGUAGE_SWITCH) { super.onDrawKeyTopVisuals(key, canvas, paint, params); drawKeyPopupHint(key, canvas, paint, params); } else { diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 92e1f5473..141436a6d 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -27,6 +27,7 @@ import com.android.inputmethod.keyboard.internal.GestureStroke.GestureStrokePara import com.android.inputmethod.keyboard.internal.GestureStrokeWithPreviewPoints; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.CollectionUtils; +import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.InputPointers; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; @@ -453,8 +454,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element { final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState(); final int code = altersCode ? key.getAltCode() : primaryCode; if (DEBUG_LISTENER) { - final String output = code == Keyboard.CODE_OUTPUT_TEXT - ? key.getOutputText() : Keyboard.printableCode(code); + final String output = code == Constants.CODE_OUTPUT_TEXT + ? key.getOutputText() : Constants.printableCode(code); Log.d(TAG, String.format("[%d] onCodeInput: %4d %4d %s%s%s", mPointerId, x, y, output, ignoreModifierKey ? " ignoreModifier" : "", altersCode ? " altersCode" : "", key.isEnabled() ? "" : " disabled")); @@ -469,9 +470,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element { // Even if the key is disabled, it should respond if it is in the altCodeWhileTyping state. if (key.isEnabled() || altersCode) { sTimeRecorder.onCodeInput(code, eventTime); - if (code == Keyboard.CODE_OUTPUT_TEXT) { + if (code == Constants.CODE_OUTPUT_TEXT) { mListener.onTextInput(key.getOutputText()); - } else if (code != Keyboard.CODE_UNSPECIFIED) { + } else if (code != Constants.CODE_UNSPECIFIED) { mListener.onCodeInput(code, x, y); } } @@ -487,7 +488,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { final boolean ignoreModifierKey = mIsInSlidingKeyInputFromModifier && key.isModifier(); if (DEBUG_LISTENER) { Log.d(TAG, String.format("[%d] onRelease : %s%s%s%s", mPointerId, - Keyboard.printableCode(primaryCode), + Constants.printableCode(primaryCode), withSliding ? " sliding" : "", ignoreModifierKey ? " ignoreModifier" : "", key.isEnabled() ? "": " disabled")); } @@ -952,8 +953,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element { + " phantom sudden move event (distance=%d) is translated to " + "up[%d,%d,%s]/down[%d,%d,%s] events", mPointerId, getDistance(x, y, lastX, lastY), - lastX, lastY, Keyboard.printableCode(oldKey.mCode), - x, y, Keyboard.printableCode(key.mCode))); + lastX, lastY, Constants.printableCode(oldKey.mCode), + x, y, Constants.printableCode(key.mCode))); } // TODO: This should be moved to outside of this nested if-clause? if (ProductionFlag.IS_EXPERIMENTAL) { @@ -978,8 +979,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element { + " bogus down-move-up event (raidus=%.2f key diagonal) is " + " translated to up[%d,%d,%s]/down[%d,%d,%s] events", mPointerId, radiusRatio, - lastX, lastY, Keyboard.printableCode(oldKey.mCode), - x, y, Keyboard.printableCode(key.mCode))); + lastX, lastY, Constants.printableCode(oldKey.mCode), + x, y, Constants.printableCode(key.mCode))); } onUpEventInternal(eventTime); onDownEventInternal(x, y, eventTime); diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java index 94fc80507..ed01f3458 100644 --- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java +++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java @@ -172,7 +172,8 @@ public final class ProximityInfo { Log.d(TAG, String.format( " [%2d] row=%d x/y/r=%7.2f/%7.2f/%5.2f %s code=%s", i, row, sweetSpotCenterXs[i], sweetSpotCenterYs[i], sweetSpotRadii[i], - row < rows ? "correct" : "default", Keyboard.printableCode(key.mCode))); + (row < rows ? "correct" : "default"), + Constants.printableCode(key.mCode))); } } } else { @@ -238,7 +239,7 @@ public final class ProximityInfo { return; } int index = 0; - if (primaryKeyCode > Keyboard.CODE_SPACE) { + if (primaryKeyCode > Constants.CODE_SPACE) { dest[index++] = primaryKeyCode; } final Key[] nearestKeys = getNearestKeys(x, y); @@ -247,7 +248,7 @@ public final class ProximityInfo { break; } final int code = key.mCode; - if (code <= Keyboard.CODE_SPACE) { + if (code <= Constants.CODE_SPACE) { break; } dest[index++] = code; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java index 2caa5eb02..9f6e2f37e 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java @@ -16,12 +16,13 @@ package com.android.inputmethod.keyboard.internal; -import static com.android.inputmethod.keyboard.Keyboard.CODE_UNSPECIFIED; +import static com.android.inputmethod.latin.Constants.CODE_OUTPUT_TEXT; +import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED; import android.text.TextUtils; -import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.CollectionUtils; +import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.StringUtils; @@ -172,7 +173,7 @@ public final class KeySpecParser { if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0) { throw new KeySpecParserError("Multiple " + LABEL_END + ": " + moreKeySpec); } - return parseCode(moreKeySpec.substring(end + 1), codesSet, Keyboard.CODE_UNSPECIFIED); + return parseCode(moreKeySpec.substring(end + 1), codesSet, CODE_UNSPECIFIED); } final String outputText = getOutputTextInternal(moreKeySpec); if (outputText != null) { @@ -181,14 +182,14 @@ public final class KeySpecParser { if (StringUtils.codePointCount(outputText) == 1) { return outputText.codePointAt(0); } - return Keyboard.CODE_OUTPUT_TEXT; + return CODE_OUTPUT_TEXT; } final String label = getLabel(moreKeySpec); // Code is automatically generated for one letter label. if (StringUtils.codePointCount(label) == 1) { return label.codePointAt(0); } - return Keyboard.CODE_OUTPUT_TEXT; + return CODE_OUTPUT_TEXT; } public static int parseCode(final String text, final KeyboardCodesSet codesSet, @@ -468,7 +469,7 @@ public final class KeySpecParser { public static int toUpperCaseOfCodeForLocale(final int code, final boolean needsToUpperCase, final Locale locale) { - if (!Keyboard.isLetterCode(code) || !needsToUpperCase) return code; + if (!Constants.isLetterCode(code) || !needsToUpperCase) return code; final String text = new String(new int[] { code } , 0, 1); final String casedText = KeySpecParser.toUpperCaseOfStringForLocale( text, needsToUpperCase, locale); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java index 840d7133d..428e31ccd 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java @@ -16,8 +16,8 @@ package com.android.inputmethod.keyboard.internal; -import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.CollectionUtils; +import com.android.inputmethod.latin.Constants; import java.util.HashMap; @@ -74,21 +74,21 @@ public final class KeyboardCodesSet { private static final int CODE_RIGHT_CURLY_BRACKET = '}'; private static final int[] DEFAULT = { - Keyboard.CODE_TAB, - Keyboard.CODE_ENTER, - Keyboard.CODE_SPACE, - Keyboard.CODE_SHIFT, - Keyboard.CODE_SWITCH_ALPHA_SYMBOL, - Keyboard.CODE_OUTPUT_TEXT, - Keyboard.CODE_DELETE, - Keyboard.CODE_SETTINGS, - Keyboard.CODE_SHORTCUT, - Keyboard.CODE_ACTION_ENTER, - Keyboard.CODE_ACTION_NEXT, - Keyboard.CODE_ACTION_PREVIOUS, - Keyboard.CODE_LANGUAGE_SWITCH, - Keyboard.CODE_RESEARCH, - Keyboard.CODE_UNSPECIFIED, + Constants.CODE_TAB, + Constants.CODE_ENTER, + Constants.CODE_SPACE, + Constants.CODE_SHIFT, + Constants.CODE_SWITCH_ALPHA_SYMBOL, + Constants.CODE_OUTPUT_TEXT, + Constants.CODE_DELETE, + Constants.CODE_SETTINGS, + Constants.CODE_SHORTCUT, + Constants.CODE_ACTION_ENTER, + Constants.CODE_ACTION_NEXT, + Constants.CODE_ACTION_PREVIOUS, + Constants.CODE_LANGUAGE_SWITCH, + Constants.CODE_RESEARCH, + Constants.CODE_UNSPECIFIED, CODE_LEFT_PARENTHESIS, CODE_RIGHT_PARENTHESIS, CODE_LESS_THAN_SIGN, diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java index e6fe50e02..642e1a18c 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java @@ -19,9 +19,9 @@ package com.android.inputmethod.keyboard.internal; import android.util.SparseIntArray; import com.android.inputmethod.keyboard.Key; -import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardId; import com.android.inputmethod.latin.CollectionUtils; +import com.android.inputmethod.latin.Constants; import java.util.ArrayList; import java.util.TreeSet; @@ -89,7 +89,7 @@ public class KeyboardParams { mKeys.add(key); updateHistogram(key); } - if (key.mCode == Keyboard.CODE_SHIFT) { + if (key.mCode == Constants.CODE_SHIFT) { mShiftKeys.add(key); } if (key.altCodeWhileTyping()) { diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index 58cc8972a..5f67ae05f 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -19,7 +19,6 @@ package com.android.inputmethod.keyboard.internal; import android.text.TextUtils; import android.util.Log; -import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.Constants; /** @@ -300,12 +299,12 @@ public final class KeyboardState { public void onPressKey(int code, boolean isSinglePointer, int autoCaps) { if (DEBUG_EVENT) { - Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code) + Log.d(TAG, "onPressKey: code=" + Constants.printableCode(code) + " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this); } - if (code == Keyboard.CODE_SHIFT) { + if (code == Constants.CODE_SHIFT) { onPressShift(); - } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { + } else if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) { onPressSymbol(); } else { mSwitchActions.cancelDoubleTapTimer(); @@ -333,12 +332,12 @@ public final class KeyboardState { public void onReleaseKey(int code, boolean withSliding) { if (DEBUG_EVENT) { - Log.d(TAG, "onReleaseKey: code=" + Keyboard.printableCode(code) + Log.d(TAG, "onReleaseKey: code=" + Constants.printableCode(code) + " sliding=" + withSliding + " " + this); } - if (code == Keyboard.CODE_SHIFT) { + if (code == Constants.CODE_SHIFT) { onReleaseShift(withSliding); - } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { + } else if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) { onReleaseSymbol(withSliding); } } @@ -365,9 +364,9 @@ public final class KeyboardState { public void onLongPressTimeout(int code) { if (DEBUG_EVENT) { - Log.d(TAG, "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + this); + Log.d(TAG, "onLongPressTimeout: code=" + Constants.printableCode(code) + " " + this); } - if (mIsAlphabetMode && code == Keyboard.CODE_SHIFT) { + if (mIsAlphabetMode && code == Constants.CODE_SHIFT) { mLongPressShiftLockFired = true; mSwitchActions.hapticAndAudioFeedback(code); } @@ -434,7 +433,7 @@ public final class KeyboardState { setShifted(MANUAL_SHIFT); mShiftKeyState.onPress(); } - mSwitchActions.startLongPressTimer(Keyboard.CODE_SHIFT); + mSwitchActions.startLongPressTimer(Constants.CODE_SHIFT); } } else { // In symbol mode, just toggle symbol and symbol more keyboard. @@ -514,7 +513,7 @@ public final class KeyboardState { } private static boolean isSpaceCharacter(int c) { - return c == Keyboard.CODE_SPACE || c == Keyboard.CODE_ENTER; + return c == Constants.CODE_SPACE || c == Constants.CODE_ENTER; } private boolean isLayoutSwitchBackCharacter(int c) { @@ -525,14 +524,14 @@ public final class KeyboardState { public void onCodeInput(int code, boolean isSinglePointer, int autoCaps) { if (DEBUG_EVENT) { - Log.d(TAG, "onCodeInput: code=" + Keyboard.printableCode(code) + Log.d(TAG, "onCodeInput: code=" + Constants.printableCode(code) + " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this); } switch (mSwitchState) { case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: - if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { + if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) { // Detected only the mode change key has been pressed, and then released. if (mIsAlphabetMode) { mSwitchState = SWITCH_STATE_ALPHA; @@ -548,7 +547,7 @@ public final class KeyboardState { } break; case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: - if (code == Keyboard.CODE_SHIFT) { + if (code == Constants.CODE_SHIFT) { // Detected only the shift key has been pressed on symbol layout, and then released. mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; } else if (isSinglePointer) { @@ -559,8 +558,8 @@ public final class KeyboardState { } break; case SWITCH_STATE_SYMBOL_BEGIN: - if (!isSpaceCharacter(code) && (Keyboard.isLetterCode(code) - || code == Keyboard.CODE_OUTPUT_TEXT)) { + if (!isSpaceCharacter(code) && (Constants.isLetterCode(code) + || code == Constants.CODE_OUTPUT_TEXT)) { mSwitchState = SWITCH_STATE_SYMBOL; } // Switch back to alpha keyboard mode immediately if user types one of the switch back @@ -581,7 +580,7 @@ public final class KeyboardState { } // If the code is a letter, update keyboard shift state. - if (Keyboard.isLetterCode(code)) { + if (Constants.isLetterCode(code)) { updateAlphabetShiftState(autoCaps); } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java index 550391b49..ca16163d4 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java +++ b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java @@ -18,7 +18,7 @@ package com.android.inputmethod.keyboard.internal; import android.text.TextUtils; -import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.StringUtils; import java.util.Locale; @@ -35,10 +35,10 @@ public final class MoreKeySpec { KeySpecParser.getLabel(moreKeySpec), needsToUpperCase, locale); final int code = KeySpecParser.toUpperCaseOfCodeForLocale( KeySpecParser.getCode(moreKeySpec, codesSet), needsToUpperCase, locale); - if (code == Keyboard.CODE_UNSPECIFIED) { + if (code == Constants.CODE_UNSPECIFIED) { // Some letter, for example German Eszett (U+00DF: "ß"), has multiple characters // upper case representation ("SS"). - mCode = Keyboard.CODE_OUTPUT_TEXT; + mCode = Constants.CODE_OUTPUT_TEXT; mOutputText = mLabel; } else { mCode = code; @@ -75,8 +75,8 @@ public final class MoreKeySpec { public String toString() { final String label = (mIconId == KeyboardIconsSet.ICON_UNDEFINED ? mLabel : KeySpecParser.PREFIX_ICON + KeyboardIconsSet.getIconName(mIconId)); - final String output = (mCode == Keyboard.CODE_OUTPUT_TEXT ? mOutputText - : Keyboard.printableCode(mCode)); + final String output = (mCode == Constants.CODE_OUTPUT_TEXT ? mOutputText + : Constants.printableCode(mCode)); if (StringUtils.codePointCount(label) == 1 && label.codePointAt(0) == mCode) { return output; } else { diff --git a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java index 91bbd54c7..024726391 100644 --- a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java +++ b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java @@ -21,7 +21,6 @@ import android.media.AudioManager; import android.view.HapticFeedbackConstants; import android.view.View; -import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.VibratorUtils; /** @@ -62,13 +61,13 @@ public final class AudioAndHapticFeedbackManager { if (mSoundOn) { final int sound; switch (primaryCode) { - case Keyboard.CODE_DELETE: + case Constants.CODE_DELETE: sound = AudioManager.FX_KEYPRESS_DELETE; break; - case Keyboard.CODE_ENTER: + case Constants.CODE_ENTER: sound = AudioManager.FX_KEYPRESS_RETURN; break; - case Keyboard.CODE_SPACE: + case Constants.CODE_SPACE: sound = AudioManager.FX_KEYPRESS_SPACEBAR; break; default: diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java index 57e12a64f..d10ed8efb 100644 --- a/java/src/com/android/inputmethod/latin/Constants.java +++ b/java/src/com/android/inputmethod/latin/Constants.java @@ -16,7 +16,11 @@ package com.android.inputmethod.latin; +import android.util.Log; + public final class Constants { + private static final String TAG = Constants.class.getSimpleName(); + public static final class Color { /** * The alpha value for fully opaque. @@ -141,6 +145,72 @@ public final class Constants { public static final int SUGGESTION_STRIP_COORDINATE = -2; public static final int SPELL_CHECKER_COORDINATE = -3; + /** + * Some common keys code. Must be positive. + */ + public static final int CODE_ENTER = '\n'; + public static final int CODE_TAB = '\t'; + public static final int CODE_SPACE = ' '; + public static final int CODE_PERIOD = '.'; + public static final int CODE_DASH = '-'; + public static final int CODE_SINGLE_QUOTE = '\''; + public static final int CODE_DOUBLE_QUOTE = '"'; + public static final int CODE_QUESTION_MARK = '?'; + public static final int CODE_EXCLAMATION_MARK = '!'; + // TODO: Check how this should work for right-to-left languages. It seems to stand + // that for rtl languages, a closing parenthesis is a left parenthesis. Is this + // managed by the font? Or is it a different char? + public static final int CODE_CLOSING_PARENTHESIS = ')'; + public static final int CODE_CLOSING_SQUARE_BRACKET = ']'; + public static final int CODE_CLOSING_CURLY_BRACKET = '}'; + public static final int CODE_CLOSING_ANGLE_BRACKET = '>'; + + /** + * Special keys code. Must be negative. + * These should be aligned with KeyboardCodesSet.ID_TO_NAME[], + * KeyboardCodesSet.DEFAULT[] and KeyboardCodesSet.RTL[] + */ + public static final int CODE_SHIFT = -1; + public static final int CODE_SWITCH_ALPHA_SYMBOL = -2; + public static final int CODE_OUTPUT_TEXT = -3; + public static final int CODE_DELETE = -4; + public static final int CODE_SETTINGS = -5; + public static final int CODE_SHORTCUT = -6; + public static final int CODE_ACTION_ENTER = -7; + public static final int CODE_ACTION_NEXT = -8; + public static final int CODE_ACTION_PREVIOUS = -9; + public static final int CODE_LANGUAGE_SWITCH = -10; + public static final int CODE_RESEARCH = -11; + // Code value representing the code is not specified. + public static final int CODE_UNSPECIFIED = -12; + + public static boolean isLetterCode(final int code) { + return code >= CODE_SPACE; + } + + public static String printableCode(final int code) { + switch (code) { + case CODE_SHIFT: return "shift"; + case CODE_SWITCH_ALPHA_SYMBOL: return "symbol"; + case CODE_OUTPUT_TEXT: return "text"; + case CODE_DELETE: return "delete"; + case CODE_SETTINGS: return "settings"; + case CODE_SHORTCUT: return "shortcut"; + case CODE_ACTION_ENTER: return "actionEnter"; + case CODE_ACTION_NEXT: return "actionNext"; + case CODE_ACTION_PREVIOUS: return "actionPrevious"; + case CODE_LANGUAGE_SWITCH: return "languageSwitch"; + case CODE_UNSPECIFIED: return "unspec"; + case CODE_TAB: return "tab"; + case CODE_ENTER: return "enter"; + default: + if (code <= 0) Log.w(TAG, "Unknown non-positive key code=" + code); + if (code < CODE_SPACE) return String.format("'\\u%02x'", code); + if (code < 0x100) return String.format("'%c'", code); + return String.format("'\\u%04x'", code); + } + } + private Constants() { // This utility class is not publicly instantiable. } diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java index 7c0448024..d1b32a2f3 100644 --- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java @@ -24,8 +24,6 @@ import android.provider.ContactsContract.Contacts; import android.text.TextUtils; import android.util.Log; -import com.android.inputmethod.keyboard.Keyboard; - import java.util.Locale; public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { @@ -194,7 +192,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { int cp = 0; for (end = startIndex + 1; end < len; end += Character.charCount(cp)) { cp = string.codePointAt(end); - if (!(cp == Keyboard.CODE_DASH || cp == Keyboard.CODE_SINGLE_QUOTE + if (!(cp == Constants.CODE_DASH || cp == Constants.CODE_SINGLE_QUOTE || Character.isLetter(cp))) { break; } diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java index c6a81033d..16cc1b35f 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -19,7 +19,6 @@ package com.android.inputmethod.latin; import android.content.Context; import android.text.TextUtils; -import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.UserHistoryForgettingCurveUtils.ForgettingCurveParams; @@ -472,8 +471,8 @@ public class ExpandableDictionary extends Dictionary { getWordsRec(children, codes, word, depth + 1, true, snr, inputIndex, skipPos, suggestions); } - } else if ((c == Keyboard.CODE_SINGLE_QUOTE - && currentChars[0] != Keyboard.CODE_SINGLE_QUOTE) || depth == skipPos) { + } else if ((c == Constants.CODE_SINGLE_QUOTE + && currentChars[0] != Constants.CODE_SINGLE_QUOTE) || depth == skipPos) { // Skip the ' and continue deeper word[depth] = c; if (children != null) { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 829b0c89d..c2afb1c4e 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1140,7 +1140,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction CharSequence lastTwo = mConnection.getTextBeforeCursor(2, 0); // It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called. if (lastTwo != null && lastTwo.length() == 2 - && lastTwo.charAt(0) == Keyboard.CODE_SPACE) { + && lastTwo.charAt(0) == Constants.CODE_SPACE) { mConnection.deleteSurroundingText(2, 0); mConnection.commitText(lastTwo.charAt(1) + " ", 1); if (ProductionFlag.IS_EXPERIMENTAL) { @@ -1156,8 +1156,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction final CharSequence lastThree = mConnection.getTextBeforeCursor(3, 0); if (lastThree != null && lastThree.length() == 3 && canBeFollowedByPeriod(lastThree.charAt(0)) - && lastThree.charAt(1) == Keyboard.CODE_SPACE - && lastThree.charAt(2) == Keyboard.CODE_SPACE) { + && lastThree.charAt(1) == Constants.CODE_SPACE + && lastThree.charAt(2) == Constants.CODE_SPACE) { mHandler.cancelDoubleSpacesTimer(); mConnection.deleteSurroundingText(2, 0); mConnection.commitText(". ", 1); @@ -1171,12 +1171,12 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // TODO: Check again whether there really ain't a better way to check this. // TODO: This should probably be language-dependant... return Character.isLetterOrDigit(codePoint) - || codePoint == Keyboard.CODE_SINGLE_QUOTE - || codePoint == Keyboard.CODE_DOUBLE_QUOTE - || codePoint == Keyboard.CODE_CLOSING_PARENTHESIS - || codePoint == Keyboard.CODE_CLOSING_SQUARE_BRACKET - || codePoint == Keyboard.CODE_CLOSING_CURLY_BRACKET - || codePoint == Keyboard.CODE_CLOSING_ANGLE_BRACKET; + || codePoint == Constants.CODE_SINGLE_QUOTE + || codePoint == Constants.CODE_DOUBLE_QUOTE + || codePoint == Constants.CODE_CLOSING_PARENTHESIS + || codePoint == Constants.CODE_CLOSING_SQUARE_BRACKET + || codePoint == Constants.CODE_CLOSING_CURLY_BRACKET + || codePoint == Constants.CODE_CLOSING_ANGLE_BRACKET; } // Callback for the {@link SuggestionStripView}, to call when the "add to dictionary" hint is @@ -1271,7 +1271,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // 16 is android.os.Build.VERSION_CODES.JELLY_BEAN but we can't write it because // we want to be able to compile against the Ice Cream Sandwich SDK. - if (Keyboard.CODE_ENTER == code && mTargetApplicationInfo != null + if (Constants.CODE_ENTER == code && mTargetApplicationInfo != null && mTargetApplicationInfo.targetSdkVersion < 16) { // Backward compatibility mode. Before Jelly bean, the keyboard would simulate // a hardware keyboard event on pressing enter or delete. This is bad for many @@ -1288,7 +1288,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction @Override public void onCodeInput(final int primaryCode, final int x, final int y) { final long when = SystemClock.uptimeMillis(); - if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { + if (primaryCode != Constants.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { mDeleteCount = 0; } mLastKeyTime = when; @@ -1303,13 +1303,13 @@ public final class LatinIME extends InputMethodService implements KeyboardAction if (!mWordComposer.isComposingWord()) mIsAutoCorrectionIndicatorOn = false; // TODO: Consolidate the double space timer, mLastKeyTime, and the space state. - if (primaryCode != Keyboard.CODE_SPACE) { + if (primaryCode != Constants.CODE_SPACE) { mHandler.cancelDoubleSpacesTimer(); } boolean didAutoCorrect = false; switch (primaryCode) { - case Keyboard.CODE_DELETE: + case Constants.CODE_DELETE: mSpaceState = SPACE_STATE_NONE; handleBackspace(spaceState); mDeleteCount++; @@ -1317,29 +1317,29 @@ public final class LatinIME extends InputMethodService implements KeyboardAction mShouldSwitchToLastSubtype = true; LatinImeLogger.logOnDelete(x, y); break; - case Keyboard.CODE_SHIFT: - case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: + case Constants.CODE_SHIFT: + case Constants.CODE_SWITCH_ALPHA_SYMBOL: // Shift and symbol key is handled in onPressKey() and onReleaseKey(). break; - case Keyboard.CODE_SETTINGS: + case Constants.CODE_SETTINGS: onSettingsKeyPressed(); break; - case Keyboard.CODE_SHORTCUT: + case Constants.CODE_SHORTCUT: mSubtypeSwitcher.switchToShortcutIME(this); break; - case Keyboard.CODE_ACTION_ENTER: + case Constants.CODE_ACTION_ENTER: performEditorAction(getActionId(switcher.getKeyboard())); break; - case Keyboard.CODE_ACTION_NEXT: + case Constants.CODE_ACTION_NEXT: performEditorAction(EditorInfo.IME_ACTION_NEXT); break; - case Keyboard.CODE_ACTION_PREVIOUS: + case Constants.CODE_ACTION_PREVIOUS: performEditorAction(EditorInfo.IME_ACTION_PREVIOUS); break; - case Keyboard.CODE_LANGUAGE_SWITCH: + case Constants.CODE_LANGUAGE_SWITCH: handleLanguageSwitchKey(); break; - case Keyboard.CODE_RESEARCH: + case Constants.CODE_RESEARCH: if (ProductionFlag.IS_EXPERIMENTAL) { ResearchLogger.getInstance().onResearchKeySelected(this); } @@ -1375,10 +1375,10 @@ public final class LatinIME extends InputMethodService implements KeyboardAction } switcher.onCodeInput(primaryCode); // Reset after any single keystroke, except shift and symbol-shift - if (!didAutoCorrect && primaryCode != Keyboard.CODE_SHIFT - && primaryCode != Keyboard.CODE_SWITCH_ALPHA_SYMBOL) + if (!didAutoCorrect && primaryCode != Constants.CODE_SHIFT + && primaryCode != Constants.CODE_SWITCH_ALPHA_SYMBOL) mLastComposedWord.deactivate(); - if (Keyboard.CODE_DELETE != primaryCode) { + if (Constants.CODE_DELETE != primaryCode) { mEnteredText = null; } mConnection.endBatchEdit(); @@ -1399,14 +1399,14 @@ public final class LatinIME extends InputMethodService implements KeyboardAction mHandler.postUpdateSuggestionStrip(); final String text = specificTldProcessingOnTextInput(rawText); if (SPACE_STATE_PHANTOM == mSpaceState) { - sendKeyCodePoint(Keyboard.CODE_SPACE); + sendKeyCodePoint(Constants.CODE_SPACE); } mConnection.commitText(text, 1); mConnection.endBatchEdit(); // Space state must be updated before calling updateShiftState mSpaceState = SPACE_STATE_NONE; mKeyboardSwitcher.updateShiftState(); - mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT); + mKeyboardSwitcher.onCodeInput(Constants.CODE_OUTPUT_TEXT); mEnteredText = text; } @@ -1562,7 +1562,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction mWordComposer.setBatchInputWord(batchInputText); mConnection.beginBatchEdit(); if (SPACE_STATE_PHANTOM == mSpaceState) { - sendKeyCodePoint(Keyboard.CODE_SPACE); + sendKeyCodePoint(Constants.CODE_SPACE); } mConnection.setComposingText(batchInputText, 1); mExpectingUpdateSelection = true; @@ -1573,7 +1573,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction } private String specificTldProcessingOnTextInput(final String text) { - if (text.length() <= 1 || text.charAt(0) != Keyboard.CODE_PERIOD + if (text.length() <= 1 || text.charAt(0) != Constants.CODE_PERIOD || !Character.isLetter(text.charAt(1))) { // Not a tld: do nothing. return text; @@ -1584,7 +1584,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // TODO: use getCodePointBeforeCursor instead to improve performance and simplify the code final CharSequence lastOne = mConnection.getTextBeforeCursor(1, 0); if (lastOne != null && lastOne.length() == 1 - && lastOne.charAt(0) == Keyboard.CODE_PERIOD) { + && lastOne.charAt(0) == Constants.CODE_PERIOD) { return text.substring(1); } else { return text; @@ -1689,7 +1689,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction private boolean maybeStripSpace(final int code, final int spaceState, final boolean isFromSuggestionStrip) { - if (Keyboard.CODE_ENTER == code && SPACE_STATE_SWAP_PUNCTUATION == spaceState) { + if (Constants.CODE_ENTER == code && SPACE_STATE_SWAP_PUNCTUATION == spaceState) { mConnection.removeTrailingSpace(); return false; } else if ((SPACE_STATE_WEAK == spaceState @@ -1718,7 +1718,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // Sanity check throw new RuntimeException("Should not be composing here"); } - sendKeyCodePoint(Keyboard.CODE_SPACE); + sendKeyCodePoint(Constants.CODE_SPACE); } // NOTE: isCursorTouchingWord() is a blocking IPC call, so it often takes several @@ -1732,7 +1732,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // the character is a single quote. The idea here is, single quote is not a // separator and it should be treated as a normal character, except in the first // position where it should not start composing a word. - isComposingWord = (Keyboard.CODE_SINGLE_QUOTE != primaryCode); + isComposingWord = (Constants.CODE_SINGLE_QUOTE != primaryCode); // Here we don't need to reset the last composed word. It will be reset // when we commit this one, if we ever do; if on the other hand we backspace // it entirely and resume suggestions on the previous word, we'd like to still @@ -1796,11 +1796,11 @@ public final class LatinIME extends InputMethodService implements KeyboardAction if (SPACE_STATE_PHANTOM == spaceState && mCurrentSettings.isPhantomSpacePromotingSymbol(primaryCode)) { - sendKeyCodePoint(Keyboard.CODE_SPACE); + sendKeyCodePoint(Constants.CODE_SPACE); } sendKeyCodePoint(primaryCode); - if (Keyboard.CODE_SPACE == primaryCode) { + if (Constants.CODE_SPACE == primaryCode) { if (mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) { if (maybeDoubleSpace()) { mSpaceState = SPACE_STATE_DOUBLE; @@ -2060,7 +2060,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction int firstChar = Character.codePointAt(suggestion, 0); if ((!mCurrentSettings.isWeakSpaceStripper(firstChar)) && (!mCurrentSettings.isWeakSpaceSwapper(firstChar))) { - sendKeyCodePoint(Keyboard.CODE_SPACE); + sendKeyCodePoint(Constants.CODE_SPACE); } } @@ -2105,7 +2105,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction && !AutoCorrection.isValidWord(mSuggest.getUnigramDictionaries(), suggestion, true); if (ProductionFlag.IS_INTERNAL) { - Stats.onSeparator((char)Keyboard.CODE_SPACE, + Stats.onSeparator((char)Constants.CODE_SPACE, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); } if (showingAddToDictionaryHint && mIsUserDictionaryAvailable) { @@ -2276,16 +2276,16 @@ public final class LatinIME extends InputMethodService implements KeyboardAction // If accessibility is on, ensure the user receives keyboard state updates. if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { switch (primaryCode) { - case Keyboard.CODE_SHIFT: + case Constants.CODE_SHIFT: AccessibleKeyboardViewProxy.getInstance().notifyShiftState(); break; - case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: + case Constants.CODE_SWITCH_ALPHA_SYMBOL: AccessibleKeyboardViewProxy.getInstance().notifySymbolsState(); break; } } - if (Keyboard.CODE_DELETE == primaryCode) { + if (Constants.CODE_DELETE == primaryCode) { // This is a stopgap solution to avoid leaving a high surrogate alone in a text view. // In the future, we need to deprecate deteleSurroundingText() and have a surrogate // pair-friendly way of deleting characters in InputConnection. diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index bf2dfbc0b..d1c96d42a 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -26,7 +26,6 @@ import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; -import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.research.ResearchLogger; @@ -590,7 +589,7 @@ public final class RichInputConnection { if (DEBUG_BATCH_NESTING) checkBatchEdit(); final CharSequence lastOne = getTextBeforeCursor(1, 0); if (lastOne != null && lastOne.length() == 1 - && lastOne.charAt(0) == Keyboard.CODE_SPACE) { + && lastOne.charAt(0) == Constants.CODE_SPACE) { deleteSurroundingText(1, 0); } } @@ -616,7 +615,7 @@ public final class RichInputConnection { CharSequence word = getWordAtCursor(settings.mWordSeparators); // We don't suggest on leading single quotes, so we have to remove them from the word if // it starts with single quotes. - while (!TextUtils.isEmpty(word) && Keyboard.CODE_SINGLE_QUOTE == word.charAt(0)) { + while (!TextUtils.isEmpty(word) && Constants.CODE_SINGLE_QUOTE == word.charAt(0)) { word = word.subSequence(1, word.length()); } if (TextUtils.isEmpty(word)) return null; @@ -668,7 +667,7 @@ public final class RichInputConnection { // NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to // enter surrogate pairs this code will have been removed. if (TextUtils.isEmpty(textBeforeCursor) - || (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1))) { + || (Constants.CODE_SPACE != textBeforeCursor.charAt(1))) { // We may only come here if the application is changing the text while we are typing. // This is quite a broken case, but not logically impossible, so we shouldn't crash, // but some debugging log may be in order. diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java index 44b75b568..043043cef 100644 --- a/java/src/com/android/inputmethod/latin/StringUtils.java +++ b/java/src/com/android/inputmethod/latin/StringUtils.java @@ -19,9 +19,6 @@ package com.android.inputmethod.latin; import android.text.InputType; import android.text.TextUtils; -//For character constants -import com.android.inputmethod.keyboard.Keyboard; - import java.util.ArrayList; import java.util.Locale; @@ -175,7 +172,7 @@ public final class StringUtils { } else { for (i = cs.length(); i > 0; i--) { final char c = cs.charAt(i - 1); - if (c != Keyboard.CODE_DOUBLE_QUOTE && c != Keyboard.CODE_SINGLE_QUOTE + if (c != Constants.CODE_DOUBLE_QUOTE && c != Constants.CODE_SINGLE_QUOTE && Character.getType(c) != Character.START_PUNCTUATION) { break; } @@ -191,11 +188,11 @@ public final class StringUtils { // if the first char that's not a space or tab is a start of line (as in \n, start of text, // or some other similar characters). int j = i; - char prevChar = Keyboard.CODE_SPACE; + char prevChar = Constants.CODE_SPACE; if (hasSpaceBefore) --j; while (j > 0) { prevChar = cs.charAt(j - 1); - if (!Character.isSpaceChar(prevChar) && prevChar != Keyboard.CODE_TAB) break; + if (!Character.isSpaceChar(prevChar) && prevChar != Constants.CODE_TAB) break; j--; } if (j <= 0 || Character.isWhitespace(prevChar)) { @@ -234,7 +231,7 @@ public final class StringUtils { // variants of English, the final period is placed within double quotes and maybe // other closing punctuation signs. This is generally not true in other languages. final char c = cs.charAt(j - 1); - if (c != Keyboard.CODE_DOUBLE_QUOTE && c != Keyboard.CODE_SINGLE_QUOTE + if (c != Constants.CODE_DOUBLE_QUOTE && c != Constants.CODE_SINGLE_QUOTE && Character.getType(c) != Character.END_PUNCTUATION) { break; } @@ -248,10 +245,10 @@ public final class StringUtils { // end of a sentence. If we have a question mark or an exclamation mark, it's the end of // a sentence. If it's neither, the only remaining case is the period so we get the opposite // case out of the way. - if (c == Keyboard.CODE_QUESTION_MARK || c == Keyboard.CODE_EXCLAMATION_MARK) { + if (c == Constants.CODE_QUESTION_MARK || c == Constants.CODE_EXCLAMATION_MARK) { return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_SENTENCES) & reqModes; } - if (c != Keyboard.CODE_PERIOD || j <= 0) { + if (c != Constants.CODE_PERIOD || j <= 0) { return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes; } @@ -301,7 +298,7 @@ public final class StringUtils { case WORD: if (Character.isLetter(c)) { state = WORD; - } else if (c == Keyboard.CODE_PERIOD) { + } else if (c == Constants.CODE_PERIOD) { state = PERIOD; } else { return caps; @@ -317,7 +314,7 @@ public final class StringUtils { case LETTER: if (Character.isLetter(c)) { state = LETTER; - } else if (c == Keyboard.CODE_PERIOD) { + } else if (c == Constants.CODE_PERIOD) { state = PERIOD; } else { return noCaps; diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index c87161bd3..3dc2ba95b 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -20,7 +20,6 @@ import android.content.Context; import android.text.TextUtils; import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; @@ -392,7 +391,7 @@ public final class Suggest { sb.append(wordInfo.mWord); } for (int i = trailingSingleQuotesCount - 1; i >= 0; --i) { - sb.appendCodePoint(Keyboard.CODE_SINGLE_QUOTE); + sb.appendCodePoint(Constants.CODE_SINGLE_QUOTE); } return new SuggestedWordInfo(sb.toString(), wordInfo.mScore, wordInfo.mKind, wordInfo.mSourceDict); diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index 229aa8a48..daff442f3 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -135,7 +135,7 @@ public final class WordComposer { mTypedWord.appendCodePoint(primaryCode); refreshSize(); if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) { - mPrimaryKeyCodes[newIndex] = primaryCode >= Keyboard.CODE_SPACE + mPrimaryKeyCodes[newIndex] = primaryCode >= Constants.CODE_SPACE ? Character.toLowerCase(primaryCode) : primaryCode; // In the batch input mode, the {@code mInputPointers} holds batch input points and // shouldn't be overridden by the "typed key" coordinates @@ -149,7 +149,7 @@ public final class WordComposer { newIndex, primaryCode, mIsFirstCharCapitalized); if (Character.isUpperCase(primaryCode)) mCapsCount++; if (Character.isDigit(primaryCode)) mDigitsCount++; - if (Keyboard.CODE_SINGLE_QUOTE == primaryCode) { + if (Constants.CODE_SINGLE_QUOTE == primaryCode) { ++mTrailingSingleQuotesCount; } else { mTrailingSingleQuotesCount = 0; @@ -236,7 +236,7 @@ public final class WordComposer { int i = mTypedWord.length(); while (i > 0) { i = mTypedWord.offsetByCodePoints(i, -1); - if (Keyboard.CODE_SINGLE_QUOTE != mTypedWord.codePointAt(i)) break; + if (Constants.CODE_SINGLE_QUOTE != mTypedWord.codePointAt(i)) break; ++mTrailingSingleQuotesCount; } } diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java index 763fd6e00..6295abe8c 100644 --- a/java/src/com/android/inputmethod/research/ResearchLogger.java +++ b/java/src/com/android/inputmethod/research/ResearchLogger.java @@ -870,7 +870,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final long time = SystemClock.uptimeMillis(); final ResearchLogger researchLogger = getInstance(); final Object[] values = { - Keyboard.printableCode(scrubDigitFromCodePoint(code)), x, y + Constants.printableCode(scrubDigitFromCodePoint(code)), x, y }; researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_ONCODEINPUT, values); if (Character.isDigit(code)) { @@ -1006,7 +1006,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang }; public static void latinIME_sendKeyCodePoint(final int code) { final Object[] values = { - Keyboard.printableCode(scrubDigitFromCodePoint(code)) + Constants.printableCode(scrubDigitFromCodePoint(code)) }; final ResearchLogger researchLogger = getInstance(); researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_SENDKEYCODEPOINT, values); @@ -1092,7 +1092,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang if (key != null) { String outputText = key.getOutputText(); final Object[] values = { - Keyboard.printableCode(scrubDigitFromCodePoint(code)), outputText == null ? null + Constants.printableCode(scrubDigitFromCodePoint(code)), outputText == null ? null : scrubDigitsFromString(outputText.toString()), x, y, ignoreModifierKey, altersCode, key.isEnabled() }; @@ -1109,7 +1109,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final boolean withSliding, final boolean ignoreModifierKey) { if (key != null) { final Object[] values = { - Keyboard.printableCode(scrubDigitFromCodePoint(primaryCode)), withSliding, + Constants.printableCode(scrubDigitFromCodePoint(primaryCode)), withSliding, ignoreModifierKey, key.isEnabled() }; getInstance().enqueuePotentiallyPrivateEvent( diff --git a/java/src/com/android/inputmethod/research/Statistics.java b/java/src/com/android/inputmethod/research/Statistics.java index eab465aa2..98491bd23 100644 --- a/java/src/com/android/inputmethod/research/Statistics.java +++ b/java/src/com/android/inputmethod/research/Statistics.java @@ -16,7 +16,7 @@ package com.android.inputmethod.research; -import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.latin.Constants; public class Statistics { // Number of characters entered during a typing session @@ -104,7 +104,7 @@ public class Statistics { public void recordChar(int codePoint, long time) { final long delta = time - mLastTapTime; - if (codePoint == Keyboard.CODE_DELETE) { + if (codePoint == Constants.CODE_DELETE) { mDeleteKeyCount++; if (delta < MIN_DELETION_INTERMISSION) { if (mIsLastKeyDeleteKey) { diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java index 1ab577557..5bba961bd 100644 --- a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java +++ b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java @@ -16,13 +16,13 @@ package com.android.inputmethod.keyboard.internal; -import static com.android.inputmethod.keyboard.Keyboard.CODE_OUTPUT_TEXT; -import static com.android.inputmethod.keyboard.Keyboard.CODE_UNSPECIFIED; import static com.android.inputmethod.keyboard.internal.KeyboardIconsSet.ICON_UNDEFINED; +import static com.android.inputmethod.latin.Constants.CODE_OUTPUT_TEXT; +import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED; import android.test.AndroidTestCase; -import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.latin.Constants; import java.util.Arrays; import java.util.Locale; @@ -69,8 +69,8 @@ public class KeySpecParserTests extends AndroidTestCase { KeyboardIconsSet.getIconName(expectedIcon), KeyboardIconsSet.getIconName(spec.mIconId)); assertEquals(message + " [code]", - Keyboard.printableCode(expectedCode), - Keyboard.printableCode(spec.mCode)); + Constants.printableCode(expectedCode), + Constants.printableCode(spec.mCode)); } private void assertParserError(String message, String moreKeySpec, String expectedLabel, diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java index 2770ed54a..c75f8269a 100644 --- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java +++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java @@ -19,7 +19,7 @@ package com.android.inputmethod.keyboard.internal; import android.test.AndroidTestCase; public class KeyboardStateTestsBase extends AndroidTestCase - implements MockKeyboardSwitcher.Constants { + implements MockKeyboardSwitcher.MockConstants { protected MockKeyboardSwitcher mSwitcher; private String mLayoutSwitchBackSymbols = ""; diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java index dd4caadf1..0213744fb 100644 --- a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java +++ b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java @@ -18,25 +18,24 @@ package com.android.inputmethod.keyboard.internal; import android.text.TextUtils; -import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.latin.Constants; public class MockKeyboardSwitcher implements KeyboardState.SwitchActions { - public interface Constants { + public interface MockConstants { // Argument for {@link KeyboardState#onPressKey} and {@link KeyboardState#onReleaseKey}. public static final boolean NOT_SLIDING = false; public static final boolean SLIDING = true; // Argument for {@link KeyboardState#onCodeInput}. public static final boolean SINGLE = true; public static final boolean MULTI = false; - public static final int CAP_MODE_OFF = - com.android.inputmethod.latin.Constants.TextUtils.CAP_MODE_OFF; + public static final int CAP_MODE_OFF = Constants.TextUtils.CAP_MODE_OFF; public static final int CAP_MODE_WORDS = TextUtils.CAP_MODE_WORDS; public static final int CAP_MODE_CHARACTERS = TextUtils.CAP_MODE_CHARACTERS; - public static final int CODE_SHIFT = Keyboard.CODE_SHIFT; - public static final int CODE_SYMBOL = Keyboard.CODE_SWITCH_ALPHA_SYMBOL; - public static final int CODE_SPACE = Keyboard.CODE_SPACE; - public static final int CODE_AUTO_CAPS_TRIGGER = Keyboard.CODE_SPACE; + public static final int CODE_SHIFT = Constants.CODE_SHIFT; + public static final int CODE_SYMBOL = Constants.CODE_SWITCH_ALPHA_SYMBOL; + public static final int CODE_SPACE = Constants.CODE_SPACE; + public static final int CODE_AUTO_CAPS_TRIGGER = Constants.CODE_SPACE; public static final int ALPHABET_UNSHIFTED = 0; public static final int ALPHABET_MANUAL_SHIFTED = 1; @@ -47,11 +46,11 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions { public static final int SYMBOLS_SHIFTED = 6; } - private int mLayout = Constants.ALPHABET_UNSHIFTED; + private int mLayout = MockConstants.ALPHABET_UNSHIFTED; - private int mAutoCapsMode = Constants.CAP_MODE_OFF; + private int mAutoCapsMode = MockConstants.CAP_MODE_OFF; // Following InputConnection's behavior. Simulating InputType.TYPE_TEXT_FLAG_CAP_WORDS. - private int mAutoCapsState = Constants.CAP_MODE_OFF; + private int mAutoCapsState = MockConstants.CAP_MODE_OFF; private boolean mIsInDoubleTapTimeout; private int mLongPressTimeoutCode; @@ -64,13 +63,13 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions { public static String getLayoutName(int layoutId) { switch (layoutId) { - case Constants.ALPHABET_UNSHIFTED: return "ALPHABET_UNSHIFTED"; - case Constants.ALPHABET_MANUAL_SHIFTED: return "ALPHABET_MANUAL_SHIFTED"; - case Constants.ALPHABET_AUTOMATIC_SHIFTED: return "ALPHABET_AUTOMATIC_SHIFTED"; - case Constants.ALPHABET_SHIFT_LOCKED: return "ALPHABET_SHIFT_LOCKED"; - case Constants.ALPHABET_SHIFT_LOCK_SHIFTED: return "ALPHABET_SHIFT_LOCK_SHIFTED"; - case Constants.SYMBOLS_UNSHIFTED: return "SYMBOLS_UNSHIFTED"; - case Constants.SYMBOLS_SHIFTED: return "SYMBOLS_SHIFTED"; + case MockConstants.ALPHABET_UNSHIFTED: return "ALPHABET_UNSHIFTED"; + case MockConstants.ALPHABET_MANUAL_SHIFTED: return "ALPHABET_MANUAL_SHIFTED"; + case MockConstants.ALPHABET_AUTOMATIC_SHIFTED: return "ALPHABET_AUTOMATIC_SHIFTED"; + case MockConstants.ALPHABET_SHIFT_LOCKED: return "ALPHABET_SHIFT_LOCKED"; + case MockConstants.ALPHABET_SHIFT_LOCK_SHIFTED: return "ALPHABET_SHIFT_LOCK_SHIFTED"; + case MockConstants.SYMBOLS_UNSHIFTED: return "SYMBOLS_UNSHIFTED"; + case MockConstants.SYMBOLS_SHIFTED: return "SYMBOLS_SHIFTED"; default: return "UNKNOWN<" + layoutId + ">"; } } @@ -86,37 +85,37 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions { @Override public void setAlphabetKeyboard() { - mLayout = Constants.ALPHABET_UNSHIFTED; + mLayout = MockConstants.ALPHABET_UNSHIFTED; } @Override public void setAlphabetManualShiftedKeyboard() { - mLayout = Constants.ALPHABET_MANUAL_SHIFTED; + mLayout = MockConstants.ALPHABET_MANUAL_SHIFTED; } @Override public void setAlphabetAutomaticShiftedKeyboard() { - mLayout = Constants.ALPHABET_AUTOMATIC_SHIFTED; + mLayout = MockConstants.ALPHABET_AUTOMATIC_SHIFTED; } @Override public void setAlphabetShiftLockedKeyboard() { - mLayout = Constants.ALPHABET_SHIFT_LOCKED; + mLayout = MockConstants.ALPHABET_SHIFT_LOCKED; } @Override public void setAlphabetShiftLockShiftedKeyboard() { - mLayout = Constants.ALPHABET_SHIFT_LOCK_SHIFTED; + mLayout = MockConstants.ALPHABET_SHIFT_LOCK_SHIFTED; } @Override public void setSymbolsKeyboard() { - mLayout = Constants.SYMBOLS_UNSHIFTED; + mLayout = MockConstants.SYMBOLS_UNSHIFTED; } @Override public void setSymbolsShiftedKeyboard() { - mLayout = Constants.SYMBOLS_SHIFTED; + mLayout = MockConstants.SYMBOLS_SHIFTED; } @Override @@ -186,10 +185,10 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions { } public void onCodeInput(int code, boolean isSinglePointer) { - if (mAutoCapsMode == Constants.CAP_MODE_WORDS) { - if (Keyboard.isLetterCode(code)) { - mAutoCapsState = (code == Constants.CODE_AUTO_CAPS_TRIGGER) - ? mAutoCapsMode : Constants.CAP_MODE_OFF; + if (mAutoCapsMode == MockConstants.CAP_MODE_WORDS) { + if (Constants.isLetterCode(code)) { + mAutoCapsState = (code == MockConstants.CODE_AUTO_CAPS_TRIGGER) + ? mAutoCapsMode : MockConstants.CAP_MODE_OFF; } } else { mAutoCapsState = mAutoCapsMode; diff --git a/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java index 2544bd87c..02047cfc4 100644 --- a/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java +++ b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java @@ -16,8 +16,6 @@ package com.android.inputmethod.latin; -import com.android.inputmethod.keyboard.Keyboard; - import android.text.style.SuggestionSpan; import android.text.style.UnderlineSpan; @@ -67,13 +65,13 @@ public class BlueUnderlineTests extends InputTestsBase { type(STRING_TO_TYPE); sleep(DELAY_TO_WAIT_FOR_UNDERLINE); runMessages(); - type(Keyboard.CODE_SPACE); + type(Constants.CODE_SPACE); sleep(DELAY_TO_WAIT_FOR_UNDERLINE); runMessages(); - type(Keyboard.CODE_DELETE); + type(Constants.CODE_DELETE); sleep(DELAY_TO_WAIT_FOR_UNDERLINE); runMessages(); - type(Keyboard.CODE_DELETE); + type(Constants.CODE_DELETE); sleep(DELAY_TO_WAIT_FOR_UNDERLINE); runMessages(); final SpanGetter suggestionSpan = new SpanGetter(mTextView.getText(), SuggestionSpan.class); diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java index 3b9eda212..38f5305de 100644 --- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java +++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java @@ -16,8 +16,6 @@ package com.android.inputmethod.latin; -import com.android.inputmethod.keyboard.Keyboard; - public class InputLogicTests extends InputTestsBase { public void testTypeWord() { @@ -32,7 +30,7 @@ public class InputLogicTests extends InputTestsBase { type(WORD_TO_TYPE); pickSuggestionManually(0, WORD_TO_TYPE); mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); - type(Keyboard.CODE_DELETE); + type(Constants.CODE_DELETE); assertEquals("press suggestion then backspace", EXPECTED_RESULT, mTextView.getText().toString()); } @@ -48,7 +46,7 @@ public class InputLogicTests extends InputTestsBase { mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); assertEquals("pick typed word over auto-correction then backspace", WORD_TO_PICK, mTextView.getText().toString()); - type(Keyboard.CODE_DELETE); + type(Constants.CODE_DELETE); assertEquals("pick typed word over auto-correction then backspace", EXPECTED_RESULT, mTextView.getText().toString()); } @@ -63,7 +61,7 @@ public class InputLogicTests extends InputTestsBase { mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); assertEquals("pick typed word over auto-correction then backspace", WORD_TO_TYPE, mTextView.getText().toString()); - type(Keyboard.CODE_DELETE); + type(Constants.CODE_DELETE); assertEquals("pick typed word over auto-correction then backspace", EXPECTED_RESULT, mTextView.getText().toString()); } @@ -79,7 +77,7 @@ public class InputLogicTests extends InputTestsBase { mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); assertEquals("pick different suggestion then backspace", WORD_TO_PICK, mTextView.getText().toString()); - type(Keyboard.CODE_DELETE); + type(Constants.CODE_DELETE); assertEquals("pick different suggestion then backspace", EXPECTED_RESULT, mTextView.getText().toString()); } @@ -100,7 +98,7 @@ public class InputLogicTests extends InputTestsBase { // And now we simulate the user actually selecting some text. mLatinIME.onUpdateSelection(typedLength, typedLength, SELECTION_START, SELECTION_END, -1, -1); - type(Keyboard.CODE_DELETE); + type(Constants.CODE_DELETE); assertEquals("delete selection", EXPECTED_RESULT, mTextView.getText().toString()); } @@ -123,7 +121,7 @@ public class InputLogicTests extends InputTestsBase { final String EXPECTED_RESULT = "tgis."; type(STRING_TO_TYPE); mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); - type(Keyboard.CODE_DELETE); + type(Constants.CODE_DELETE); assertEquals("auto-correct with period then revert", EXPECTED_RESULT, mTextView.getText().toString()); } @@ -133,7 +131,7 @@ public class InputLogicTests extends InputTestsBase { final String EXPECTED_RESULT = "tgis "; type(STRING_TO_TYPE); mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); - type(Keyboard.CODE_DELETE); + type(Constants.CODE_DELETE); assertEquals("auto-correct with space then revert", EXPECTED_RESULT, mTextView.getText().toString()); } @@ -143,7 +141,7 @@ public class InputLogicTests extends InputTestsBase { final String EXPECTED_RESULT = "this"; type(STRING_TO_TYPE); mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); - type(Keyboard.CODE_DELETE); + type(Constants.CODE_DELETE); assertEquals("auto-correct with space does not revert", EXPECTED_RESULT, mTextView.getText().toString()); } @@ -159,7 +157,7 @@ public class InputLogicTests extends InputTestsBase { final String STRING_TO_TYPE = "this "; final String EXPECTED_RESULT = "this "; type(STRING_TO_TYPE); - type(Keyboard.CODE_DELETE); + type(Constants.CODE_DELETE); assertEquals("double space make a period", EXPECTED_RESULT, mTextView.getText().toString()); } @@ -173,7 +171,7 @@ public class InputLogicTests extends InputTestsBase { mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION); mLatinIME.onUpdateSelection(typedLength, typedLength, NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1); - type(Keyboard.CODE_DELETE); + type(Constants.CODE_DELETE); assertEquals("auto correct then move cursor to start of line then backspace", EXPECTED_RESULT, mTextView.getText().toString()); } @@ -188,7 +186,7 @@ public class InputLogicTests extends InputTestsBase { mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION); mLatinIME.onUpdateSelection(typedLength, typedLength, NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1); - type(Keyboard.CODE_DELETE); + type(Constants.CODE_DELETE); assertEquals("auto correct then move cursor then backspace", EXPECTED_RESULT, mTextView.getText().toString()); } @@ -264,7 +262,7 @@ public class InputLogicTests extends InputTestsBase { final String WORD_TO_TYPE = "this"; type(WORD_TO_TYPE); for (int i = 0; i < WORD_TO_TYPE.length(); ++i) { - type(Keyboard.CODE_DELETE); + type(Constants.CODE_DELETE); } assertEquals("delete whole composing word", "", mTextView.getText().toString()); } -- cgit v1.2.3-83-g751a From cfbfb1c50a18234c5415a9897f62b0d456036885 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Mon, 29 Oct 2012 17:25:13 +0900 Subject: Remove reference of android.util.Log in Constants class This is a follow up of Iee01d4d2. Change-Id: I0bcd349d317d9f7d40ef0574e72c640f9f990c5d --- java/src/com/android/inputmethod/latin/Constants.java | 4 ---- 1 file changed, 4 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java index d10ed8efb..fa6ff1848 100644 --- a/java/src/com/android/inputmethod/latin/Constants.java +++ b/java/src/com/android/inputmethod/latin/Constants.java @@ -16,11 +16,8 @@ package com.android.inputmethod.latin; -import android.util.Log; public final class Constants { - private static final String TAG = Constants.class.getSimpleName(); - public static final class Color { /** * The alpha value for fully opaque. @@ -204,7 +201,6 @@ public final class Constants { case CODE_TAB: return "tab"; case CODE_ENTER: return "enter"; default: - if (code <= 0) Log.w(TAG, "Unknown non-positive key code=" + code); if (code < CODE_SPACE) return String.format("'\\u%02x'", code); if (code < 0x100) return String.format("'%c'", code); return String.format("'\\u%04x'", code); -- cgit v1.2.3-83-g751a From c7318bbc0b47662799d2f7a01e5b53edb43ebf2a Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Mon, 29 Oct 2012 18:40:37 +0900 Subject: Fix possible NPE Bug: 7398904 Change-Id: I6b7aba7a9bf52ca494cb4390b19525c98790bd49 --- java/src/com/android/inputmethod/latin/LatinIME.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index c2afb1c4e..c66ff9504 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1932,7 +1932,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction private SuggestedWords getSuggestedWords(final int sessionId) { final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); - if (keyboard == null) { + if (keyboard == null || mSuggest == null) { return SuggestedWords.EMPTY; } final String typedWord = mWordComposer.getTypedWord(); -- cgit v1.2.3-83-g751a From 51a0ef8c59ea590b6e5e80a82fc75bf244084270 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Wed, 31 Oct 2012 15:35:20 +0900 Subject: Add a plumbing option to dicttool info. Also align the `porcelain' option to the diff command that was used mistakenly. Bug: 7388665 Change-Id: Ic0e1b98c62ce37b2e909384a0370af4458563703 --- .../latin/makedict/FusionDictionary.java | 14 +++++++++----- .../android/inputmethod/latin/dicttool/Diff.java | 10 +++++----- .../android/inputmethod/latin/dicttool/Info.java | 22 +++++++++++++++++----- 3 files changed, 31 insertions(+), 15 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java index c588824fe..b0b3777df 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java +++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java @@ -290,19 +290,23 @@ public final class FusionDictionary implements Iterable { } @Override public String toString() { // Convenience method - return toString(0); + return toString(0, false); } - public String toString(final int indentCount) { + public String toString(final int indentCount, final boolean plumbing) { final StringBuilder indent = new StringBuilder(); - for (int i = 0; i < indentCount; ++i) { - indent.append(" "); + if (plumbing) { + indent.append("H:"); + } else { + for (int i = 0; i < indentCount; ++i) { + indent.append(" "); + } } final StringBuilder s = new StringBuilder(); for (final String optionKey : mAttributes.keySet()) { s.append(indent); s.append(optionKey); s.append(" = "); - if ("date".equals(optionKey)) { + if ("date".equals(optionKey) && !plumbing) { // Date needs a number of milliseconds, but the dictionary contains seconds s.append(new Date( 1000 * Long.parseLong(mAttributes.get(optionKey))).toString()); diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java index 9548f2509..855c026b9 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java @@ -34,7 +34,7 @@ public class Diff extends Dicttool.Command { @Override public String getHelp() { return COMMAND + " [-p] : shows differences between two dictionaries.\n" - + " If -p (porcelain) option is given, produce output suitable for a script"; + + " If -p (plumbing) option is given, produce output suitable for a script"; } @Override @@ -42,15 +42,15 @@ public class Diff extends Dicttool.Command { if (mArgs.length < 2) { throw new RuntimeException("Not enough arguments for command " + COMMAND); } - final boolean porcelain; + final boolean plumbing; if ("-p".equals(mArgs[0])) { - porcelain = true; + plumbing = true; mArgs = Arrays.copyOfRange(mArgs, 1, mArgs.length); if (mArgs.length != 2) { // There should be only 2 arguments left throw new RuntimeException("Wrong number of arguments for command " + COMMAND); } } else { - porcelain = false; + plumbing = false; } final FusionDictionary dict0 = BinaryDictOffdeviceUtils.getDictionary(mArgs[0], false /* report */); @@ -58,7 +58,7 @@ public class Diff extends Dicttool.Command { final FusionDictionary dict1 = BinaryDictOffdeviceUtils.getDictionary(mArgs[1], false /* report */); if (null == dict1) throw new RuntimeException("Can't read dictionary " + mArgs[1]); - if (!porcelain) { + if (!plumbing) { System.out.println("Header :"); diffHeaders(dict0, dict1); if (languageDiffers(dict0, dict1)) { diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java index d91a409d3..f2894544f 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java @@ -22,6 +22,7 @@ import com.android.inputmethod.latin.makedict.FusionDictionary.CharGroup; import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; import com.android.inputmethod.latin.makedict.Word; +import java.util.Arrays; import java.util.ArrayList; public class Info extends Dicttool.Command { @@ -35,9 +36,9 @@ public class Info extends Dicttool.Command { return COMMAND + " : prints various information about a dictionary file"; } - private static void showInfo(final FusionDictionary dict) { + private static void showInfo(final FusionDictionary dict, final boolean plumbing) { System.out.println("Header attributes :"); - System.out.print(dict.mOptions.toString(2)); + System.out.print(dict.mOptions.toString(2, plumbing)); int wordCount = 0; int bigramCount = 0; int shortcutCount = 0; @@ -62,7 +63,8 @@ public class Info extends Dicttool.Command { + " whitelist entries)"); } - private static void showWordInfo(final FusionDictionary dict, final String word) { + private static void showWordInfo(final FusionDictionary dict, final String word, + final boolean plumbing) { final CharGroup group = FusionDictionary.findWordInTree(dict.mRoot, word); if (null == group) { System.out.println(word + " is not in the dictionary"); @@ -101,15 +103,25 @@ public class Info extends Dicttool.Command { if (mArgs.length < 1) { throw new RuntimeException("Not enough arguments for command " + COMMAND); } + final boolean plumbing; + if ("-p".equals(mArgs[0])) { + plumbing = true; + mArgs = Arrays.copyOfRange(mArgs, 1, mArgs.length); + if (mArgs.length != 1) { // There should be only 1 argument left + throw new RuntimeException("Wrong number of arguments for command " + COMMAND); + } + } else { + plumbing = false; + } final String filename = mArgs[0]; final boolean hasWordArguments = (1 == mArgs.length); final FusionDictionary dict = BinaryDictOffdeviceUtils.getDictionary(filename, hasWordArguments /* report */); if (hasWordArguments) { - showInfo(dict); + showInfo(dict, plumbing); } else { for (int i = 1; i < mArgs.length; ++i) { - showWordInfo(dict, mArgs[i]); + showWordInfo(dict, mArgs[i], plumbing); } } } -- cgit v1.2.3-83-g751a From 1e61493c50082264caaef862df02b1ccc84dc396 Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Mon, 29 Oct 2012 18:06:22 +0900 Subject: Use 32-bit code points for suggestions output This is a multi-project commit with Ic43dd666 bug: 6526418 Change-Id: I39c1acb4e91d04cd8a4ec5a943c8cf575da75ebc --- .../inputmethod/latin/BinaryDictionary.java | 36 +++++----- ..._android_inputmethod_latin_BinaryDictionary.cpp | 56 +++++++-------- native/jni/src/bigram_dictionary.cpp | 31 +++++---- native/jni/src/bigram_dictionary.h | 16 ++--- native/jni/src/binary_format.h | 35 +++++----- native/jni/src/char_utils.h | 30 ++++---- native/jni/src/correction.cpp | 75 ++++++++++---------- native/jni/src/correction.h | 45 ++++++------ native/jni/src/defines.h | 43 ++++-------- native/jni/src/dictionary.cpp | 11 ++- native/jni/src/dictionary.h | 12 ++-- native/jni/src/gesture/gesture_decoder_wrapper.h | 11 ++- .../src/gesture/incremental_decoder_interface.h | 7 +- .../jni/src/gesture/incremental_decoder_wrapper.h | 11 ++- native/jni/src/proximity_info_state.cpp | 41 +++++------ native/jni/src/proximity_info_state.h | 61 +++++++++-------- native/jni/src/terminal_attributes.h | 10 ++- native/jni/src/unigram_dictionary.cpp | 80 ++++++++++------------ native/jni/src/unigram_dictionary.h | 23 +++---- native/jni/src/words_priority_queue.h | 58 ++++++++-------- 20 files changed, 329 insertions(+), 363 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 80af4b9fa..a7024d1d8 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -51,8 +51,7 @@ public final class BinaryDictionary extends Dictionary { private long mNativeDict; private final Locale mLocale; private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH]; - // TODO: The below should be int[] mOutputCodePoints - private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_RESULTS]; + private final int[] mOutputCodePoints = new int[MAX_WORD_LENGTH * MAX_RESULTS]; private final int[] mSpaceIndices = new int[MAX_SPACES]; private final int[] mOutputScores = new int[MAX_RESULTS]; private final int[] mOutputTypes = new int[MAX_RESULTS]; @@ -88,9 +87,9 @@ public final class BinaryDictionary extends Dictionary { * @param useFullEditDistance whether to use the full edit distance in suggestions * @param dictType the dictionary type, as a human-readable string */ - public BinaryDictionary(final Context context, - final String filename, final long offset, final long length, - final boolean useFullEditDistance, final Locale locale, final String dictType) { + public BinaryDictionary(final Context context, final String filename, final long offset, + final long length, final boolean useFullEditDistance, final Locale locale, + final String dictType) { super(dictType); mLocale = locale; mUseFullEditDistance = useFullEditDistance; @@ -109,10 +108,10 @@ public final class BinaryDictionary extends Dictionary { private native int getSuggestionsNative(long dict, long proximityInfo, long traverseSession, int[] xCoordinates, int[] yCoordinates, int[] times, int[] pointerIds, int[] inputCodePoints, int codesSize, int commitPoint, boolean isGesture, - int[] prevWordCodePointArray, boolean useFullEditDistance, char[] outputChars, + int[] prevWordCodePointArray, boolean useFullEditDistance, int[] outputCodePoints, int[] outputScores, int[] outputIndices, int[] outputTypes); - private static native float calcNormalizedScoreNative(char[] before, char[] after, int score); - private static native int editDistanceNative(char[] before, char[] after); + private static native float calcNormalizedScoreNative(int[] before, int[] after, int score); + private static native int editDistanceNative(int[] before, int[] after); // TODO: Move native dict into session private final void loadDictionary(final String path, final long startOffset, @@ -153,7 +152,8 @@ public final class BinaryDictionary extends Dictionary { proximityInfo.getNativeProximityInfo(), getTraverseSession(sessionId).getSession(), ips.getXCoordinates(), ips.getYCoordinates(), ips.getTimes(), ips.getPointerIds(), mInputCodePoints, codesSize, 0 /* commitPoint */, isGesture, prevWordCodePointArray, - mUseFullEditDistance, mOutputChars, mOutputScores, mSpaceIndices, mOutputTypes); + mUseFullEditDistance, mOutputCodePoints, mOutputScores, mSpaceIndices, + mOutputTypes); final int count = Math.min(tmpCount, MAX_PREDICTIONS); final ArrayList suggestions = CollectionUtils.newArrayList(); @@ -161,14 +161,14 @@ public final class BinaryDictionary extends Dictionary { if (composerSize > 0 && mOutputScores[j] < 1) break; final int start = j * MAX_WORD_LENGTH; int len = 0; - while (len < MAX_WORD_LENGTH && mOutputChars[start + len] != 0) { + while (len < MAX_WORD_LENGTH && mOutputCodePoints[start + len] != 0) { ++len; } if (len > 0) { final int score = SuggestedWordInfo.KIND_WHITELIST == mOutputTypes[j] ? SuggestedWordInfo.MAX_SCORE : mOutputScores[j]; - suggestions.add(new SuggestedWordInfo( - new String(mOutputChars, start, len), score, mOutputTypes[j], mDictType)); + suggestions.add(new SuggestedWordInfo(new String(mOutputCodePoints, start, len), + score, mOutputTypes[j], mDictType)); } } return suggestions; @@ -180,14 +180,16 @@ public final class BinaryDictionary extends Dictionary { public static float calcNormalizedScore(final String before, final String after, final int score) { - return calcNormalizedScoreNative(before.toCharArray(), after.toCharArray(), score); + return calcNormalizedScoreNative(StringUtils.toCodePointArray(before), + StringUtils.toCodePointArray(after), score); } public static int editDistance(final String before, final String after) { if (before == null || after == null) { throw new IllegalArgumentException(); } - return editDistanceNative(before.toCharArray(), after.toCharArray()); + return editDistanceNative(StringUtils.toCodePointArray(before), + StringUtils.toCodePointArray(after)); } @Override @@ -206,9 +208,9 @@ public final class BinaryDictionary extends Dictionary { // calls when checking for changes in an entire dictionary. public boolean isValidBigram(final String word1, final String word2) { if (TextUtils.isEmpty(word1) || TextUtils.isEmpty(word2)) return false; - final int[] chars1 = StringUtils.toCodePointArray(word1); - final int[] chars2 = StringUtils.toCodePointArray(word2); - return isValidBigramNative(mNativeDict, chars1, chars2); + final int[] codePoints1 = StringUtils.toCodePointArray(word1); + final int[] codePoints2 = StringUtils.toCodePointArray(word2); + return isValidBigramNative(mNativeDict, codePoints1, codePoints2); } @Override diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp index 42f7da9d3..5b8d1119d 100644 --- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp +++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp @@ -132,7 +132,7 @@ static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, jintArray yCoordinatesArray, jintArray timesArray, jintArray pointerIdsArray, jintArray inputCodePointsArray, jint arraySize, jint commitPoint, jboolean isGesture, jintArray prevWordCodePointsForBigrams, jboolean useFullEditDistance, - jcharArray outputCharsArray, jintArray scoresArray, jintArray spaceIndicesArray, + jintArray outputCodePointsArray, jintArray scoresArray, jintArray spaceIndicesArray, jintArray outputTypesArray) { Dictionary *dictionary = reinterpret_cast(dict); if (!dictionary) return 0; @@ -162,16 +162,15 @@ static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, } // Output values - // TODO: Should be "outputCodePointsLength" and "int outputCodePoints[]" - const jsize outputCharsLength = env->GetArrayLength(outputCharsArray); - unsigned short outputChars[outputCharsLength]; + const jsize outputCodePointsLength = env->GetArrayLength(outputCodePointsArray); + int outputCodePoints[outputCodePointsLength]; const jsize scoresLength = env->GetArrayLength(scoresArray); int scores[scoresLength]; const jsize spaceIndicesLength = env->GetArrayLength(spaceIndicesArray); int spaceIndices[spaceIndicesLength]; const jsize outputTypesLength = env->GetArrayLength(outputTypesArray); int outputTypes[outputTypesLength]; - memset(outputChars, 0, sizeof(outputChars)); + memset(outputCodePoints, 0, sizeof(outputCodePoints)); memset(scores, 0, sizeof(scores)); memset(spaceIndices, 0, sizeof(spaceIndices)); memset(outputTypes, 0, sizeof(outputTypes)); @@ -180,16 +179,15 @@ static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, if (isGesture || arraySize > 0) { count = dictionary->getSuggestions(pInfo, traverseSession, xCoordinates, yCoordinates, times, pointerIds, inputCodePoints, arraySize, prevWordCodePoints, - prevWordCodePointsLength, commitPoint, isGesture, useFullEditDistance, outputChars, - scores, spaceIndices, outputTypes); + prevWordCodePointsLength, commitPoint, isGesture, useFullEditDistance, + outputCodePoints, scores, spaceIndices, outputTypes); } else { count = dictionary->getBigrams(prevWordCodePoints, prevWordCodePointsLength, - inputCodePoints, arraySize, outputChars, scores, outputTypes); + inputCodePoints, arraySize, outputCodePoints, scores, outputTypes); } // Copy back the output values - // TODO: Should be SetIntArrayRegion() - env->SetCharArrayRegion(outputCharsArray, 0, outputCharsLength, outputChars); + env->SetIntArrayRegion(outputCodePointsArray, 0, outputCodePointsLength, outputCodePoints); env->SetIntArrayRegion(scoresArray, 0, scoresLength, scores); env->SetIntArrayRegion(spaceIndicesArray, 0, spaceIndicesLength, spaceIndices); env->SetIntArrayRegion(outputTypesArray, 0, outputTypesLength, outputTypes); @@ -221,29 +219,27 @@ static jboolean latinime_BinaryDictionary_isValidBigram(JNIEnv *env, jobject obj } static jfloat latinime_BinaryDictionary_calcNormalizedScore(JNIEnv *env, jobject object, - jcharArray before, jcharArray after, jint score) { + jintArray before, jintArray after, jint score) { jsize beforeLength = env->GetArrayLength(before); jsize afterLength = env->GetArrayLength(after); - jchar beforeChars[beforeLength]; - jchar afterChars[afterLength]; - env->GetCharArrayRegion(before, 0, beforeLength, beforeChars); - env->GetCharArrayRegion(after, 0, afterLength, afterChars); - return Correction::RankingAlgorithm::calcNormalizedScore( - static_cast(beforeChars), beforeLength, - static_cast(afterChars), afterLength, score); + int beforeCodePoints[beforeLength]; + int afterCodePoints[afterLength]; + env->GetIntArrayRegion(before, 0, beforeLength, beforeCodePoints); + env->GetIntArrayRegion(after, 0, afterLength, afterCodePoints); + return Correction::RankingAlgorithm::calcNormalizedScore(beforeCodePoints, beforeLength, + afterCodePoints, afterLength, score); } -static jint latinime_BinaryDictionary_editDistance(JNIEnv *env, jobject object, - jcharArray before, jcharArray after) { +static jint latinime_BinaryDictionary_editDistance(JNIEnv *env, jobject object, jintArray before, + jintArray after) { jsize beforeLength = env->GetArrayLength(before); jsize afterLength = env->GetArrayLength(after); - jchar beforeChars[beforeLength]; - jchar afterChars[afterLength]; - env->GetCharArrayRegion(before, 0, beforeLength, beforeChars); - env->GetCharArrayRegion(after, 0, afterLength, afterChars); - return Correction::RankingAlgorithm::editDistance( - static_cast(beforeChars), beforeLength, - static_cast(afterChars), afterLength); + int beforeCodePoints[beforeLength]; + int afterCodePoints[afterLength]; + env->GetIntArrayRegion(before, 0, beforeLength, beforeCodePoints); + env->GetIntArrayRegion(after, 0, afterLength, afterCodePoints); + return Correction::RankingAlgorithm::editDistance(beforeCodePoints, beforeLength, + afterCodePoints, afterLength); } static void latinime_BinaryDictionary_close(JNIEnv *env, jobject object, jlong dict) { @@ -279,15 +275,15 @@ static JNINativeMethod sMethods[] = { {"openNative", "(Ljava/lang/String;JJIIII)J", reinterpret_cast(latinime_BinaryDictionary_open)}, {"closeNative", "(J)V", reinterpret_cast(latinime_BinaryDictionary_close)}, - {"getSuggestionsNative", "(JJJ[I[I[I[I[IIIZ[IZ[C[I[I[I)I", + {"getSuggestionsNative", "(JJJ[I[I[I[I[IIIZ[IZ[I[I[I[I)I", reinterpret_cast(latinime_BinaryDictionary_getSuggestions)}, {"getFrequencyNative", "(J[I)I", reinterpret_cast(latinime_BinaryDictionary_getFrequency)}, {"isValidBigramNative", "(J[I[I)Z", reinterpret_cast(latinime_BinaryDictionary_isValidBigram)}, - {"calcNormalizedScoreNative", "([C[CI)F", + {"calcNormalizedScoreNative", "([I[II)F", reinterpret_cast(latinime_BinaryDictionary_calcNormalizedScore)}, - {"editDistanceNative", "([C[C)I", + {"editDistanceNative", "([I[I)I", reinterpret_cast(latinime_BinaryDictionary_editDistance)} }; diff --git a/native/jni/src/bigram_dictionary.cpp b/native/jni/src/bigram_dictionary.cpp index dade4f16b..f89dd1615 100644 --- a/native/jni/src/bigram_dictionary.cpp +++ b/native/jni/src/bigram_dictionary.cpp @@ -36,13 +36,13 @@ BigramDictionary::BigramDictionary(const unsigned char *dict, int maxWordLength, BigramDictionary::~BigramDictionary() { } -bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequency, - int *bigramFreq, unsigned short *bigramChars, int *outputTypes) const { +bool BigramDictionary::addWordBigram(int *word, int length, int frequency, int *bigramFreq, + int *bigramCodePoints, int *outputTypes) const { word[length] = 0; if (DEBUG_DICT) { #ifdef FLAG_DBG char s[length + 1]; - for (int i = 0; i <= length; i++) s[i] = word[i]; + for (int i = 0; i <= length; i++) s[i] = static_cast(word[i]); AKLOGI("Bigram: Found word = %s, freq = %d :", s, frequency); #endif } @@ -51,7 +51,8 @@ bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequ int insertAt = 0; while (insertAt < MAX_PREDICTIONS) { if (frequency > bigramFreq[insertAt] || (bigramFreq[insertAt] == frequency - && length < Dictionary::wideStrLen(bigramChars + insertAt * MAX_WORD_LENGTH))) { + && length < Dictionary::wideStrLen( + bigramCodePoints + insertAt * MAX_WORD_LENGTH))) { break; } insertAt++; @@ -65,10 +66,10 @@ bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequ (MAX_PREDICTIONS - insertAt - 1) * sizeof(bigramFreq[0])); bigramFreq[insertAt] = frequency; outputTypes[insertAt] = Dictionary::KIND_PREDICTION; - memmove(bigramChars + (insertAt + 1) * MAX_WORD_LENGTH, - bigramChars + insertAt * MAX_WORD_LENGTH, - (MAX_PREDICTIONS - insertAt - 1) * sizeof(bigramChars[0]) * MAX_WORD_LENGTH); - unsigned short *dest = bigramChars + insertAt * MAX_WORD_LENGTH; + memmove(bigramCodePoints + (insertAt + 1) * MAX_WORD_LENGTH, + bigramCodePoints + insertAt * MAX_WORD_LENGTH, + (MAX_PREDICTIONS - insertAt - 1) * sizeof(bigramCodePoints[0]) * MAX_WORD_LENGTH); + int *dest = bigramCodePoints + insertAt * MAX_WORD_LENGTH; while (length--) { *dest++ = *word++; } @@ -86,7 +87,7 @@ bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequ * prevWordLength: its length. * inputCodes: what user typed, in the same format as for UnigramDictionary::getSuggestions. * codesSize: the size of the codes array. - * bigramChars: an array for output, at the same format as outwords for getSuggestions. + * bigramCodePoints: an array for output, at the same format as outwords for getSuggestions. * bigramFreq: an array to output frequencies. * outputTypes: an array to output types. * This method returns the number of bigrams this word has, for backward compatibility. @@ -97,8 +98,8 @@ bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequ * and the bigrams are used to boost unigram result scores, it makes little sense to * reduce their scope to the ones that match the first letter. */ -int BigramDictionary::getBigrams(const int32_t *prevWord, int prevWordLength, int *inputCodes, - int codesSize, unsigned short *bigramChars, int *bigramFreq, int *outputTypes) const { +int BigramDictionary::getBigrams(const int *prevWord, int prevWordLength, int *inputCodes, + int codesSize, int *bigramCodePoints, int *bigramFreq, int *outputTypes) const { // TODO: remove unused arguments, and refrain from storing stuff in members of this class // TODO: have "in" arguments before "out" ones, and make out args explicit in the name @@ -117,7 +118,7 @@ int BigramDictionary::getBigrams(const int32_t *prevWord, int prevWordLength, in int bigramCount = 0; do { bigramFlags = BinaryFormat::getFlagsAndForwardPointer(root, &pos); - uint16_t bigramBuffer[MAX_WORD_LENGTH]; + int bigramBuffer[MAX_WORD_LENGTH]; int unigramFreq = 0; const int bigramPos = BinaryFormat::getAttributeAddressAndForwardPointer(root, bigramFlags, &pos); @@ -134,7 +135,7 @@ int BigramDictionary::getBigrams(const int32_t *prevWord, int prevWordLength, in // here, but it can't get too bad. const int frequency = BinaryFormat::computeFrequencyForBigram(unigramFreq, bigramFreqTemp); - if (addWordBigram(bigramBuffer, length, frequency, bigramFreq, bigramChars, + if (addWordBigram(bigramBuffer, length, frequency, bigramFreq, bigramCodePoints, outputTypes)) { ++bigramCount; } @@ -190,12 +191,12 @@ void BigramDictionary::fillBigramAddressToFrequencyMapAndFilter(const int32_t *p } while (0 != (BinaryFormat::FLAG_ATTRIBUTE_HAS_NEXT & bigramFlags)); } -bool BigramDictionary::checkFirstCharacter(unsigned short *word, int *inputCodes) const { +bool BigramDictionary::checkFirstCharacter(int *word, int *inputCodes) const { // Checks whether this word starts with same character or neighboring characters of // what user typed. int maxAlt = MAX_ALTERNATIVES; - const unsigned short firstBaseChar = toBaseLowerCase(*word); + const int firstBaseChar = toBaseLowerCase(*word); while (maxAlt > 0) { if (toBaseLowerCase(*inputCodes) == firstBaseChar) { return true; diff --git a/native/jni/src/bigram_dictionary.h b/native/jni/src/bigram_dictionary.h index 5f11ae822..150192de2 100644 --- a/native/jni/src/bigram_dictionary.h +++ b/native/jni/src/bigram_dictionary.h @@ -27,23 +27,23 @@ namespace latinime { class BigramDictionary { public: BigramDictionary(const unsigned char *dict, int maxWordLength, int maxPredictions); - int getBigrams(const int32_t *word, int length, int *inputCodes, int codesSize, - unsigned short *outWords, int *frequencies, int *outputTypes) const; - void fillBigramAddressToFrequencyMapAndFilter(const int32_t *prevWord, const int prevWordLength, + int getBigrams(const int *word, int length, int *inputCodes, int codesSize, int *outWords, + int *frequencies, int *outputTypes) const; + void fillBigramAddressToFrequencyMapAndFilter(const int *prevWord, const int prevWordLength, std::map *map, uint8_t *filter) const; - bool isValidBigram(const int32_t *word1, int length1, const int32_t *word2, int length2) const; + bool isValidBigram(const int *word1, int length1, const int *word2, int length2) const; ~BigramDictionary(); private: DISALLOW_IMPLICIT_CONSTRUCTORS(BigramDictionary); - bool addWordBigram(unsigned short *word, int length, int frequency, - int *bigramFreq, unsigned short *bigramChars, int *outputTypes) const; + bool addWordBigram(int *word, int length, int frequency, int *bigramFreq, int *bigramCodePoints, + int *outputTypes) const; int getBigramAddress(int *pos, bool advance); int getBigramFreq(int *pos); void searchForTerminalNode(int addressLookingFor, int frequency); bool getFirstBitOfByte(int *pos) { return (DICT[*pos] & 0x80) > 0; } bool getSecondBitOfByte(int *pos) { return (DICT[*pos] & 0x40) > 0; } - bool checkFirstCharacter(unsigned short *word, int *inputCodes) const; - int getBigramListPositionForWord(const int32_t *prevWord, const int prevWordLength, + bool checkFirstCharacter(int *word, int *inputCodes) const; + int getBigramListPositionForWord(const int *prevWord, const int prevWordLength, const bool forceLowerCaseSearch) const; const unsigned char *DICT; diff --git a/native/jni/src/binary_format.h b/native/jni/src/binary_format.h index eec52e323..c0aec50d7 100644 --- a/native/jni/src/binary_format.h +++ b/native/jni/src/binary_format.h @@ -84,7 +84,7 @@ class BinaryFormat { static unsigned int getFlags(const uint8_t *const dict); static int getGroupCountAndForwardPointer(const uint8_t *const dict, int *pos); static uint8_t getFlagsAndForwardPointer(const uint8_t *const dict, int *pos); - static int32_t getCodePointAndForwardPointer(const uint8_t *const dict, int *pos); + static int getCodePointAndForwardPointer(const uint8_t *const dict, int *pos); static int readFrequencyWithoutMovingPointer(const uint8_t *const dict, const int pos); static int skipOtherCharacters(const uint8_t *const dict, const int pos); static int skipChildrenPosition(const uint8_t flags, const int pos); @@ -98,10 +98,10 @@ class BinaryFormat { static int getAttributeAddressAndForwardPointer(const uint8_t *const dict, const uint8_t flags, int *pos); static int getAttributeFrequencyFromFlags(const int flags); - static int getTerminalPosition(const uint8_t *const root, const int32_t *const inWord, + static int getTerminalPosition(const uint8_t *const root, const int *const inWord, const int length, const bool forceLowerCaseSearch); static int getWordAtAddress(const uint8_t *const root, const int address, const int maxDepth, - uint16_t *outWord, int *outUnigramFrequency); + int *outWord, int *outUnigramFrequency); static int computeFrequencyForBigram(const int unigramFreq, const int bigramFreq); static int getProbability(const int position, const std::map *bigramMap, const uint8_t *bigramFilter, const int unigramFreq); @@ -176,17 +176,17 @@ inline uint8_t BinaryFormat::getFlagsAndForwardPointer(const uint8_t *const dict return dict[(*pos)++]; } -inline int32_t BinaryFormat::getCodePointAndForwardPointer(const uint8_t *const dict, int *pos) { +inline int BinaryFormat::getCodePointAndForwardPointer(const uint8_t *const dict, int *pos) { const int origin = *pos; - const int32_t codePoint = dict[origin]; + const int codePoint = dict[origin]; if (codePoint < MINIMAL_ONE_BYTE_CHARACTER_VALUE) { if (codePoint == CHARACTER_ARRAY_TERMINATOR) { *pos = origin + 1; return NOT_A_CODE_POINT; } else { *pos = origin + 3; - const int32_t char_1 = codePoint << 16; - const int32_t char_2 = char_1 + (dict[origin + 1] << 8); + const int char_1 = codePoint << 16; + const int char_2 = char_1 + (dict[origin + 1] << 8); return char_2 + dict[origin + 2]; } } else { @@ -202,7 +202,7 @@ inline int BinaryFormat::readFrequencyWithoutMovingPointer(const uint8_t *const inline int BinaryFormat::skipOtherCharacters(const uint8_t *const dict, const int pos) { int currentPos = pos; - int32_t character = dict[currentPos++]; + int character = dict[currentPos++]; while (CHARACTER_ARRAY_TERMINATOR != character) { if (character < MINIMAL_ONE_BYTE_CHARACTER_VALUE) { currentPos += MULTIPLE_BYTE_CHARACTER_ADDITIONAL_SIZE; @@ -352,8 +352,8 @@ inline int BinaryFormat::getAttributeFrequencyFromFlags(const int flags) { // This function gets the byte position of the last chargroup of the exact matching word in the // dictionary. If no match is found, it returns NOT_VALID_WORD. -inline int BinaryFormat::getTerminalPosition(const uint8_t *const root, - const int32_t *const inWord, const int length, const bool forceLowerCaseSearch) { +inline int BinaryFormat::getTerminalPosition(const uint8_t *const root, const int *const inWord, + const int length, const bool forceLowerCaseSearch) { int pos = 0; int wordPos = 0; @@ -362,14 +362,14 @@ inline int BinaryFormat::getTerminalPosition(const uint8_t *const root, // there was no match (or we would have found it). if (wordPos >= length) return NOT_VALID_WORD; int charGroupCount = BinaryFormat::getGroupCountAndForwardPointer(root, &pos); - const int32_t wChar = forceLowerCaseSearch ? toLowerCase(inWord[wordPos]) : inWord[wordPos]; + const int wChar = forceLowerCaseSearch ? toLowerCase(inWord[wordPos]) : inWord[wordPos]; while (true) { // If there are no more character groups in this node, it means we could not // find a matching character for this depth, therefore there is no match. if (0 >= charGroupCount) return NOT_VALID_WORD; const int charGroupPos = pos; const uint8_t flags = BinaryFormat::getFlagsAndForwardPointer(root, &pos); - int32_t character = BinaryFormat::getCodePointAndForwardPointer(root, &pos); + int character = BinaryFormat::getCodePointAndForwardPointer(root, &pos); if (character == wChar) { // This is the correct node. Only one character group may start with the same // char within a node, so either we found our match in this node, or there is @@ -439,7 +439,7 @@ inline int BinaryFormat::getTerminalPosition(const uint8_t *const root, * Return value : the length of the word, of 0 if the word was not found. */ inline int BinaryFormat::getWordAtAddress(const uint8_t *const root, const int address, - const int maxDepth, uint16_t *outWord, int *outUnigramFrequency) { + const int maxDepth, int *outWord, int *outUnigramFrequency) { int pos = 0; int wordPos = 0; @@ -457,13 +457,13 @@ inline int BinaryFormat::getWordAtAddress(const uint8_t *const root, const int a --charGroupCount) { const int startPos = pos; const uint8_t flags = getFlagsAndForwardPointer(root, &pos); - const int32_t character = getCodePointAndForwardPointer(root, &pos); + const int character = getCodePointAndForwardPointer(root, &pos); if (address == startPos) { // We found the address. Copy the rest of the word in the buffer and return // the length. outWord[wordPos] = character; if (FLAG_HAS_MULTIPLE_CHARS & flags) { - int32_t nextChar = getCodePointAndForwardPointer(root, &pos); + int nextChar = getCodePointAndForwardPointer(root, &pos); // We count chars in order to avoid infinite loops if the file is broken or // if there is some other bug int charCount = maxDepth; @@ -522,13 +522,12 @@ inline int BinaryFormat::getWordAtAddress(const uint8_t *const root, const int a if (0 != lastCandidateGroupPos) { const uint8_t lastFlags = getFlagsAndForwardPointer(root, &lastCandidateGroupPos); - const int32_t lastChar = + const int lastChar = getCodePointAndForwardPointer(root, &lastCandidateGroupPos); // We copy all the characters in this group to the buffer outWord[wordPos] = lastChar; if (FLAG_HAS_MULTIPLE_CHARS & lastFlags) { - int32_t nextChar = - getCodePointAndForwardPointer(root, &lastCandidateGroupPos); + int nextChar = getCodePointAndForwardPointer(root, &lastCandidateGroupPos); int charCount = maxDepth; while (-1 != nextChar && --charCount > 0) { outWord[++wordPos] = nextChar; diff --git a/native/jni/src/char_utils.h b/native/jni/src/char_utils.h index 9008e364c..b42de6607 100644 --- a/native/jni/src/char_utils.h +++ b/native/jni/src/char_utils.h @@ -18,22 +18,23 @@ #define LATINIME_CHAR_UTILS_H #include -#include + +#include "defines.h" namespace latinime { -inline static bool isAsciiUpper(unsigned short c) { +inline static bool isAsciiUpper(int c) { // Note: isupper(...) reports false positives for some Cyrillic characters, causing them to // be incorrectly lower-cased using toAsciiLower(...) rather than latin_tolower(...). return (c >= 'A' && c <= 'Z'); } -inline static unsigned short toAsciiLower(unsigned short c) { +inline static int toAsciiLower(int c) { return c - 'A' + 'a'; } -inline static bool isAscii(unsigned short c) { - return isascii(static_cast(c)) != 0; +inline static bool isAscii(int c) { + return isascii(c) != 0; } unsigned short latin_tolower(const unsigned short c); @@ -44,33 +45,32 @@ unsigned short latin_tolower(const unsigned short c); * if c is not a combined character, or the base character if it * is combined. */ - static const int BASE_CHARS_SIZE = 0x0500; -extern const uint16_t BASE_CHARS[BASE_CHARS_SIZE]; +extern const unsigned short BASE_CHARS[BASE_CHARS_SIZE]; -inline static unsigned short toBaseChar(unsigned short c) { +inline static int toBaseCodePoint(int c) { if (c < BASE_CHARS_SIZE) { - return BASE_CHARS[c]; + return static_cast(BASE_CHARS[c]); } return c; } -inline static unsigned short toLowerCase(const unsigned short c) { +inline static int toLowerCase(const int c) { if (isAsciiUpper(c)) { return toAsciiLower(c); } else if (isAscii(c)) { return c; } - return latin_tolower(c); + return static_cast(latin_tolower(static_cast(c))); } -inline static unsigned short toBaseLowerCase(const unsigned short c) { - return toLowerCase(toBaseChar(c)); +inline static int toBaseLowerCase(const int c) { + return toLowerCase(toBaseCodePoint(c)); } -inline static bool isSkippableChar(const uint16_t character) { +inline static bool isSkippableCodePoint(const int codePoint) { // TODO: Do not hardcode here - return character == '\'' || character == '-'; + return codePoint == KEYCODE_SINGLE_QUOTE || codePoint == KEYCODE_HYPHEN_MINUS; } } // namespace latinime diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp index d57b0e370..949158a0b 100644 --- a/native/jni/src/correction.cpp +++ b/native/jni/src/correction.cpp @@ -60,8 +60,8 @@ inline static void dumpEditDistance10ForDebug(int *editDistanceTable, } } -inline static void calcEditDistanceOneStep(int *editDistanceTable, const unsigned short *input, - const int inputSize, const unsigned short *output, const int outputLength) { +inline static void calcEditDistanceOneStep(int *editDistanceTable, const int *input, + const int inputSize, const int *output, const int outputLength) { // TODO: Make sure that editDistance[0 ~ MAX_WORD_LENGTH_INTERNAL] is not touched. // Let dp[i][j] be editDistanceTable[i * (inputSize + 1) + j]. // Assuming that dp[0][0] ... dp[outputLength - 1][inputSize] are already calculated, @@ -71,10 +71,10 @@ inline static void calcEditDistanceOneStep(int *editDistanceTable, const unsigne const int *const prevprev = outputLength >= 2 ? editDistanceTable + (outputLength - 2) * (inputSize + 1) : 0; current[0] = outputLength; - const uint32_t co = toBaseLowerCase(output[outputLength - 1]); - const uint32_t prevCO = outputLength >= 2 ? toBaseLowerCase(output[outputLength - 2]) : 0; + const int co = toBaseLowerCase(output[outputLength - 1]); + const int prevCO = outputLength >= 2 ? toBaseLowerCase(output[outputLength - 2]) : 0; for (int i = 1; i <= inputSize; ++i) { - const uint32_t ci = toBaseLowerCase(input[i - 1]); + const int ci = toBaseLowerCase(input[i - 1]); const uint16_t cost = (ci == co) ? 0 : 1; current[i] = min(current[i - 1] + 1, min(prev[i] + 1, prev[i - 1] + cost)); if (i >= 2 && prevprev && ci == prevCO && co == toBaseLowerCase(input[i - 2])) { @@ -94,11 +94,9 @@ inline static int getCurrentEditDistance(int *editDistanceTable, const int editD ////////////////////// // inline functions // ////////////////////// -static const char SINGLE_QUOTE = '\''; - -inline bool Correction::isSingleQuote(const unsigned short c) { - const unsigned short userTypedChar = mProximityInfoState.getPrimaryCharAt(mInputIndex); - return (c == SINGLE_QUOTE && userTypedChar != SINGLE_QUOTE); +inline bool Correction::isSingleQuote(const int c) { + const int userTypedChar = mProximityInfoState.getPrimaryCodePointAt(mInputIndex); + return (c == KEYCODE_SINGLE_QUOTE && userTypedChar != KEYCODE_SINGLE_QUOTE); } //////////////// @@ -162,22 +160,22 @@ bool Correction::sameAsTyped() { } int Correction::getFreqForSplitMultipleWords(const int *freqArray, const int *wordLengthArray, - const int wordCount, const bool isSpaceProximity, const unsigned short *word) { + const int wordCount, const bool isSpaceProximity, const int *word) { return Correction::RankingAlgorithm::calcFreqForSplitMultipleWords(freqArray, wordLengthArray, wordCount, this, isSpaceProximity, word); } -int Correction::getFinalProbability(const int probability, unsigned short **word, int *wordLength) { +int Correction::getFinalProbability(const int probability, int **word, int *wordLength) { return getFinalProbabilityInternal(probability, word, wordLength, mInputSize); } -int Correction::getFinalProbabilityForSubQueue(const int probability, unsigned short **word, - int *wordLength, const int inputSize) { +int Correction::getFinalProbabilityForSubQueue(const int probability, int **word, int *wordLength, + const int inputSize) { return getFinalProbabilityInternal(probability, word, wordLength, inputSize); } -int Correction::getFinalProbabilityInternal(const int probability, unsigned short **word, - int *wordLength, const int inputSize) { +int Correction::getFinalProbabilityInternal(const int probability, int **word, int *wordLength, + const int inputSize) { const int outputIndex = mTerminalOutputIndex; const int inputIndex = mTerminalInputIndex; *wordLength = outputIndex + 1; @@ -273,15 +271,15 @@ bool Correction::needsToPrune() const { || (!mDoAutoCompletion && (mOutputIndex > mInputSize)); } -void Correction::addCharToCurrentWord(const int32_t c) { +void Correction::addCharToCurrentWord(const int c) { mWord[mOutputIndex] = c; - const unsigned short *primaryInputWord = mProximityInfoState.getPrimaryInputWord(); - calcEditDistanceOneStep(mEditDistanceTable, primaryInputWord, mInputSize, - mWord, mOutputIndex + 1); + const int *primaryInputWord = mProximityInfoState.getPrimaryInputWord(); + calcEditDistanceOneStep(mEditDistanceTable, primaryInputWord, mInputSize, mWord, + mOutputIndex + 1); } -Correction::CorrectionType Correction::processSkipChar( - const int32_t c, const bool isTerminal, const bool inputIndexIncremented) { +Correction::CorrectionType Correction::processSkipChar(const int c, const bool isTerminal, + const bool inputIndexIncremented) { addCharToCurrentWord(c); mTerminalInputIndex = mInputIndex - (inputIndexIncremented ? 1 : 0); mTerminalOutputIndex = mOutputIndex; @@ -309,8 +307,7 @@ inline bool isProximityCharOrEquivalentChar(ProximityType type) { return type == EQUIVALENT_CHAR || type == NEAR_PROXIMITY_CHAR; } -Correction::CorrectionType Correction::processCharAndCalcState( - const int32_t c, const bool isTerminal) { +Correction::CorrectionType Correction::processCharAndCalcState(const int c, const bool isTerminal) { const int correctionCount = (mSkippedCount + mExcessiveCount + mTransposedCount); if (correctionCount > mMaxErrors) { return processUnrelatedCorrectionType(); @@ -628,10 +625,10 @@ Correction::CorrectionType Correction::processCharAndCalcState( } } -inline static int getQuoteCount(const unsigned short *word, const int length) { +inline static int getQuoteCount(const int *word, const int length) { int quoteCount = 0; for (int i = 0; i < length; ++i) { - if (word[i] == SINGLE_QUOTE) { + if (word[i] == KEYCODE_SINGLE_QUOTE) { ++quoteCount; } } @@ -639,7 +636,7 @@ inline static int getQuoteCount(const unsigned short *word, const int length) { } inline static bool isUpperCase(unsigned short c) { - return isAsciiUpper(toBaseChar(c)); + return isAsciiUpper(toBaseCodePoint(c)); } ////////////////////// @@ -672,7 +669,7 @@ int Correction::RankingAlgorithm::calculateFinalProbability(const int inputIndex // TODO: use mExcessiveCount const int matchCount = inputSize - correction->mProximityCount - excessiveCount; - const unsigned short *word = correction->mWord; + const int *word = correction->mWord; const bool skipped = skippedCount > 0; const int quoteDiffCount = max(0, getQuoteCount(word, outputLength) @@ -911,7 +908,7 @@ int Correction::RankingAlgorithm::calculateFinalProbability(const int inputIndex /* static */ int Correction::RankingAlgorithm::calcFreqForSplitMultipleWords( const int *freqArray, const int *wordLengthArray, const int wordCount, - const Correction *correction, const bool isSpaceProximity, const unsigned short *word) { + const Correction *correction, const bool isSpaceProximity, const int *word) { const int typedLetterMultiplier = correction->TYPED_LETTER_MULTIPLIER; bool firstCapitalizedWordDemotion = false; @@ -1040,9 +1037,8 @@ int Correction::RankingAlgorithm::calcFreqForSplitMultipleWords( } /* Damerau-Levenshtein distance */ -inline static int editDistanceInternal( - int *editDistanceTable, const unsigned short *before, - const int beforeLength, const unsigned short *after, const int afterLength) { +inline static int editDistanceInternal(int *editDistanceTable, const int *before, + const int beforeLength, const int *after, const int afterLength) { // dp[li][lo] dp[a][b] = dp[ a * lo + b] int *dp = editDistanceTable; const int li = beforeLength + 1; @@ -1056,9 +1052,9 @@ inline static int editDistanceInternal( for (int i = 0; i < li - 1; ++i) { for (int j = 0; j < lo - 1; ++j) { - const uint32_t ci = toBaseLowerCase(before[i]); - const uint32_t co = toBaseLowerCase(after[j]); - const uint16_t cost = (ci == co) ? 0 : 1; + const int ci = toBaseLowerCase(before[i]); + const int co = toBaseLowerCase(after[j]); + const int cost = (ci == co) ? 0 : 1; dp[(i + 1) * lo + (j + 1)] = min(dp[i * lo + (j + 1)] + 1, min(dp[(i + 1) * lo + j] + 1, dp[i * lo + j] + cost)); if (i > 0 && j > 0 && ci == toBaseLowerCase(after[j - 1]) @@ -1080,8 +1076,8 @@ inline static int editDistanceInternal( return dp[li * lo - 1]; } -int Correction::RankingAlgorithm::editDistance(const unsigned short *before, - const int beforeLength, const unsigned short *after, const int afterLength) { +int Correction::RankingAlgorithm::editDistance(const int *before, const int beforeLength, + const int *after, const int afterLength) { int table[(beforeLength + 1) * (afterLength + 1)]; return editDistanceInternal(table, before, beforeLength, after, afterLength); } @@ -1109,9 +1105,8 @@ int Correction::RankingAlgorithm::editDistance(const unsigned short *before, // So, we can normalize original score by dividing powf(2, min(b.l(),a.l())) * 255 * 2. /* static */ -float Correction::RankingAlgorithm::calcNormalizedScore(const unsigned short *before, - const int beforeLength, const unsigned short *after, const int afterLength, - const int score) { +float Correction::RankingAlgorithm::calcNormalizedScore(const int *before, const int beforeLength, + const int *after, const int afterLength, const int score) { if (0 == beforeLength || 0 == afterLength) { return 0; } diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h index a099853e6..fff24b048 100644 --- a/native/jni/src/correction.h +++ b/native/jni/src/correction.h @@ -78,14 +78,13 @@ class Correction { return ++mTotalTraverseCount; } - int getFreqForSplitMultipleWords( - const int *freqArray, const int *wordLengthArray, const int wordCount, - const bool isSpaceProximity, const unsigned short *word); - int getFinalProbability(const int probability, unsigned short **word, int *wordLength); - int getFinalProbabilityForSubQueue(const int probability, unsigned short **word, - int *wordLength, const int inputSize); + int getFreqForSplitMultipleWords(const int *freqArray, const int *wordLengthArray, + const int wordCount, const bool isSpaceProximity, const int *word); + int getFinalProbability(const int probability, int **word, int *wordLength); + int getFinalProbabilityForSubQueue(const int probability, int **word, int *wordLength, + const int inputSize); - CorrectionType processCharAndCalcState(const int32_t c, const bool isTerminal); + CorrectionType processCharAndCalcState(const int c, const bool isTerminal); ///////////////////////// // Tree helper methods @@ -110,28 +109,28 @@ class Correction { const int inputSize); static int calcFreqForSplitMultipleWords(const int *freqArray, const int *wordLengthArray, const int wordCount, const Correction *correction, const bool isSpaceProximity, - const unsigned short *word); - static float calcNormalizedScore(const unsigned short *before, const int beforeLength, - const unsigned short *after, const int afterLength, const int score); - static int editDistance(const unsigned short *before, - const int beforeLength, const unsigned short *after, const int afterLength); + const int *word); + static float calcNormalizedScore(const int *before, const int beforeLength, + const int *after, const int afterLength, const int score); + static int editDistance(const int *before, const int beforeLength, const int *after, + const int afterLength); private: static const int MAX_INITIAL_SCORE = 255; }; // proximity info state - void initInputParams(const ProximityInfo *proximityInfo, const int32_t *inputCodes, + void initInputParams(const ProximityInfo *proximityInfo, const int *inputCodes, const int inputSize, const int *xCoordinates, const int *yCoordinates) { mProximityInfoState.initInputParams(0, MAX_POINT_TO_KEY_LENGTH, proximityInfo, inputCodes, inputSize, xCoordinates, yCoordinates, 0, 0, false); } - const unsigned short *getPrimaryInputWord() const { + const int *getPrimaryInputWord() const { return mProximityInfoState.getPrimaryInputWord(); } - unsigned short getPrimaryCharAt(const int index) const { - return mProximityInfoState.getPrimaryCharAt(index); + int getPrimaryCodePointAt(const int index) const { + return mProximityInfoState.getPrimaryCodePointAt(index); } private: @@ -214,13 +213,13 @@ class Correction { inline void incrementInputIndex(); inline void incrementOutputIndex(); inline void startToTraverseAllNodes(); - inline bool isSingleQuote(const unsigned short c); - inline CorrectionType processSkipChar( - const int32_t c, const bool isTerminal, const bool inputIndexIncremented); + inline bool isSingleQuote(const int c); + inline CorrectionType processSkipChar(const int c, const bool isTerminal, + const bool inputIndexIncremented); inline CorrectionType processUnrelatedCorrectionType(); - inline void addCharToCurrentWord(const int32_t c); - inline int getFinalProbabilityInternal(const int probability, unsigned short **word, - int *wordLength, const int inputSize); + inline void addCharToCurrentWord(const int c); + inline int getFinalProbabilityInternal(const int probability, int **word, int *wordLength, + const int inputSize); static const int TYPED_LETTER_MULTIPLIER = 2; static const int FULL_WORD_MULTIPLIER = 2; @@ -240,7 +239,7 @@ class Correction { uint8_t mTotalTraverseCount; // The following arrays are state buffer. - unsigned short mWord[MAX_WORD_LENGTH_INTERNAL]; + int mWord[MAX_WORD_LENGTH_INTERNAL]; int mDistances[MAX_WORD_LENGTH_INTERNAL]; // Edit distance calculation requires a buffer with (N+1)^2 length for the input length N. diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h index 942068a49..095487416 100644 --- a/native/jni/src/defines.h +++ b/native/jni/src/defines.h @@ -30,17 +30,15 @@ #define DUMP_RESULT(words, frequencies, maxWordCount, maxWordLength) do { \ dumpResult(words, frequencies, maxWordCount, maxWordLength); } while (0) #define DUMP_WORD(word, length) do { dumpWord(word, length); } while (0) -#define DUMP_WORD_INT(word, length) do { dumpWordInt(word, length); } while (0) -// TODO: INTS_TO_CHARS -#define SHORTS_TO_CHARS(input, length, output) do { \ - shortArrayToCharArray(input, length, output); } while (0) +#define INTS_TO_CHARS(input, length, output) do { \ + intArrayToCharArray(input, length, output); } while (0) -static inline void dumpWordInfo(const unsigned short *word, const int length, - const int rank, const int frequency) { +static inline void dumpWordInfo(const int *word, const int length, const int rank, + const int frequency) { static char charBuf[50]; int i = 0; for (; i < length; ++i) { - const unsigned short c = word[i]; + const int c = word[i]; if (c == 0) { break; } @@ -53,8 +51,7 @@ static inline void dumpWordInfo(const unsigned short *word, const int length, } } -static inline void dumpResult( - const unsigned short *outWords, const int *frequencies, const int maxWordCounts, +static inline void dumpResult(const int *outWords, const int *frequencies, const int maxWordCounts, const int maxWordLength) { AKLOGI("--- DUMP RESULT ---------"); for (int i = 0; i < maxWordCounts; ++i) { @@ -63,11 +60,11 @@ static inline void dumpResult( AKLOGI("-------------------------"); } -static inline void dumpWord(const unsigned short *word, const int length) { +static inline void dumpWord(const int *word, const int length) { static char charBuf[50]; int i = 0; for (; i < length; ++i) { - const unsigned short c = word[i]; + const int c = word[i]; if (c == 0) { break; } @@ -80,22 +77,10 @@ static inline void dumpWord(const unsigned short *word, const int length) { } } -static inline void dumpWordInt(const int *word, const int length) { - static char charBuf[50]; - - for (int i = 0; i < length; ++i) { - charBuf[i] = word[i]; - } - charBuf[length] = 0; - AKLOGI("i[ %s ]", charBuf); -} - -// TODO: Change this to intArrayToCharArray -static inline void shortArrayToCharArray( - const unsigned short *input, const int length, char *output) { +static inline void intArrayToCharArray(const int *input, const int length, char *output) { int i = 0; - for (;i < length; ++i) { - const unsigned short c = input[i]; + for (; i < length; ++i) { + const int c = input[i]; if (c == 0) { break; } @@ -137,11 +122,9 @@ static inline void showStackTrace() { #define AKLOGI(fmt, ...) #define DUMP_RESULT(words, frequencies, maxWordCount, maxWordLength) #define DUMP_WORD(word, length) -#define DUMP_WORD_INT(word, length) #define ASSERT(success) #define SHOW_STACK_TRACE -// TODO: INTS_TO_CHARS -#define SHORTS_TO_CHARS(input, length, output) +#define INTS_TO_CHARS(input, length, output) #endif #ifdef FLAG_DO_PROFILE @@ -286,6 +269,8 @@ static inline void prof_out(void) { #define NOT_A_PROBABILITY (-1) #define KEYCODE_SPACE ' ' +#define KEYCODE_SINGLE_QUOTE '\'' +#define KEYCODE_HYPHEN_MINUS '-' #define CALIBRATE_SCORE_BY_TOUCH_COORDINATES true diff --git a/native/jni/src/dictionary.cpp b/native/jni/src/dictionary.cpp index 81789ccfc..5fbe0461b 100644 --- a/native/jni/src/dictionary.cpp +++ b/native/jni/src/dictionary.cpp @@ -54,11 +54,10 @@ Dictionary::~Dictionary() { } int Dictionary::getSuggestions(ProximityInfo *proximityInfo, void *traverseSession, - int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, - int *codes, int codesSize, int *prevWordChars, - int prevWordLength, int commitPoint, bool isGesture, - bool useFullEditDistance, unsigned short *outWords, - int *frequencies, int *spaceIndices, int *outputTypes) const { + int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *codes, + int codesSize, int *prevWordChars, int prevWordLength, int commitPoint, bool isGesture, + bool useFullEditDistance, int *outWords, int *frequencies, int *spaceIndices, + int *outputTypes) const { int result = 0; if (isGesture) { DicTraverseWrapper::initDicTraverseSession( @@ -83,7 +82,7 @@ int Dictionary::getSuggestions(ProximityInfo *proximityInfo, void *traverseSessi } int Dictionary::getBigrams(const int32_t *word, int length, int *codes, int codesSize, - unsigned short *outWords, int *frequencies, int *outputTypes) const { + int *outWords, int *frequencies, int *outputTypes) const { if (length <= 0) return 0; return mBigramDictionary->getBigrams(word, length, codes, codesSize, outWords, frequencies, outputTypes); diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h index 120ca5f7f..2ca00ab63 100644 --- a/native/jni/src/dictionary.h +++ b/native/jni/src/dictionary.h @@ -47,11 +47,11 @@ class Dictionary { int getSuggestions(ProximityInfo *proximityInfo, void *traverseSession, int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *codes, int codesSize, int *prevWordChars, int prevWordLength, int commitPoint, bool isGesture, - bool useFullEditDistance, unsigned short *outWords, - int *frequencies, int *spaceIndices, int *outputTypes) const; + bool useFullEditDistance, int *outWords, int *frequencies, int *spaceIndices, + int *outputTypes) const; - int getBigrams(const int32_t *word, int length, int *codes, int codesSize, - unsigned short *outWords, int *frequencies, int *outputTypes) const; + int getBigrams(const int32_t *word, int length, int *codes, int codesSize, int *outWords, + int *frequencies, int *outputTypes) const; int getFrequency(const int32_t *word, int length) const; bool isValidBigram(const int32_t *word1, int length1, const int32_t *word2, int length2) const; @@ -68,7 +68,7 @@ class Dictionary { // public static utility methods // static inline methods should be defined in the header file - static int wideStrLen(unsigned short *str); + static int wideStrLen(int *str); private: DISALLOW_IMPLICIT_CONSTRUCTORS(Dictionary); @@ -88,7 +88,7 @@ class Dictionary { // public static utility methods // static inline methods should be defined in the header file -inline int Dictionary::wideStrLen(unsigned short *str) { +inline int Dictionary::wideStrLen(int *str) { if (!str) return 0; int length = 0; while (*str) { diff --git a/native/jni/src/gesture/gesture_decoder_wrapper.h b/native/jni/src/gesture/gesture_decoder_wrapper.h index 92e1ded49..eb80bd2e2 100644 --- a/native/jni/src/gesture/gesture_decoder_wrapper.h +++ b/native/jni/src/gesture/gesture_decoder_wrapper.h @@ -38,15 +38,14 @@ class GestureDecoderWrapper : public IncrementalDecoderInterface { } int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs, - int *times, int *pointerIds, int *codes, int inputSize, int commitPoint, - unsigned short *outWords, int *frequencies, int *outputIndices, - int *outputTypes) const { + int *times, int *pointerIds, int *codes, int inputSize, int commitPoint, int *outWords, + int *frequencies, int *outputIndices, int *outputTypes) const { if (!mIncrementalDecoderInterface) { return 0; } - return mIncrementalDecoderInterface->getSuggestions( - pInfo, traverseSession, inputXs, inputYs, times, pointerIds, codes, - inputSize, commitPoint, outWords, frequencies, outputIndices, outputTypes); + return mIncrementalDecoderInterface->getSuggestions(pInfo, traverseSession, inputXs, + inputYs, times, pointerIds, codes, inputSize, commitPoint, outWords, frequencies, + outputIndices, outputTypes); } static void setGestureDecoderFactoryMethod( diff --git a/native/jni/src/gesture/incremental_decoder_interface.h b/native/jni/src/gesture/incremental_decoder_interface.h index d1395aab9..e41513dbc 100644 --- a/native/jni/src/gesture/incremental_decoder_interface.h +++ b/native/jni/src/gesture/incremental_decoder_interface.h @@ -28,10 +28,9 @@ class ProximityInfo; class IncrementalDecoderInterface { public: - virtual int getSuggestions(ProximityInfo *pInfo, void *traverseSession, - int *inputXs, int *inputYs, int *times, int *pointerIds, int *codes, - int inputSize, int commitPoint, unsigned short *outWords, int *frequencies, - int *outputIndices, int *outputTypes) const = 0; + virtual int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, + int *inputYs, int *times, int *pointerIds, int *codes, int inputSize, int commitPoint, + int *outWords, int *frequencies, int *outputIndices, int *outputTypes) const = 0; IncrementalDecoderInterface() { }; virtual ~IncrementalDecoderInterface() { }; private: diff --git a/native/jni/src/gesture/incremental_decoder_wrapper.h b/native/jni/src/gesture/incremental_decoder_wrapper.h index da7afdb8a..691d4952d 100644 --- a/native/jni/src/gesture/incremental_decoder_wrapper.h +++ b/native/jni/src/gesture/incremental_decoder_wrapper.h @@ -38,15 +38,14 @@ class IncrementalDecoderWrapper : public IncrementalDecoderInterface { } int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs, - int *times, int *pointerIds, int *codes, int inputSize, int commitPoint, - unsigned short *outWords, int *frequencies, int *outputIndices, - int *outputTypes) const { + int *times, int *pointerIds, int *codes, int inputSize, int commitPoint, int *outWords, + int *frequencies, int *outputIndices, int *outputTypes) const { if (!mIncrementalDecoderInterface) { return 0; } - return mIncrementalDecoderInterface->getSuggestions( - pInfo, traverseSession, inputXs, inputYs, times, pointerIds, codes, - inputSize, commitPoint, outWords, frequencies, outputIndices, outputTypes); + return mIncrementalDecoderInterface->getSuggestions(pInfo, traverseSession, inputXs, + inputYs, times, pointerIds, codes, inputSize, commitPoint, outWords, frequencies, + outputIndices, outputTypes); } static void setIncrementalDecoderFactoryMethod( diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp index d41acdace..987a27b80 100644 --- a/native/jni/src/proximity_info_state.cpp +++ b/native/jni/src/proximity_info_state.cpp @@ -34,7 +34,7 @@ const float ProximityInfoState::NOT_A_DISTANCE_FLOAT = -1.0f; const int ProximityInfoState::NOT_A_CODE = -1; void ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength, - const ProximityInfo *proximityInfo, const int32_t *const inputCodes, const int inputSize, + const ProximityInfo *proximityInfo, const int *const inputCodes, const int inputSize, const int *const xCoordinates, const int *const yCoordinates, const int *const times, const int *const pointerIds, const bool isGeometric) { @@ -63,7 +63,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi // - mNormalizedSquaredDistances // TODO: Merge for (int i = 0; i < inputSize; ++i) { - const int32_t primaryKey = inputCodes[i]; + const int primaryKey = inputCodes[i]; const int x = xCoordinates[i]; const int y = yCoordinates[i]; int *proximities = &mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL]; @@ -146,7 +146,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi AKLOGI("Init ProximityInfoState: (%d)PID = %d", i, pid); } if (pointerId == pid) { - const int c = isGeometric ? NOT_A_COORDINATE : getPrimaryCharAt(i); + const int c = isGeometric ? NOT_A_COORDINATE : getPrimaryCodePointAt(i); const int x = proximityOnly ? NOT_A_COORDINATE : xCoordinates[i]; const int y = proximityOnly ? NOT_A_COORDINATE : yCoordinates[i]; const int time = times ? times[i] : -1; @@ -306,12 +306,12 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi && xCoordinates && yCoordinates; if (!isGeometric && pointerId == 0) { for (int i = 0; i < inputSize; ++i) { - mPrimaryInputWord[i] = getPrimaryCharAt(i); + mPrimaryInputWord[i] = getPrimaryCodePointAt(i); } for (int i = 0; i < mInputSize && mTouchPositionCorrectionEnabled; ++i) { - const int *proximityChars = getProximityCharsAt(i); - const int primaryKey = proximityChars[0]; + const int *proximityCodePoints = getProximityCodePointsAt(i); + const int primaryKey = proximityCodePoints[0]; const int x = xCoordinates[i]; const int y = yCoordinates[i]; if (DEBUG_PROXIMITY_CHARS) { @@ -319,11 +319,12 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi a += 0; AKLOGI("--- Primary = %c, x = %d, y = %d", primaryKey, x, y); } - for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL && proximityChars[j] > 0; ++j) { - const int currentChar = proximityChars[j]; + for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL && proximityCodePoints[j] > 0; + ++j) { + const int currentCodePoint = proximityCodePoints[j]; const float squaredDistance = hasInputCoordinates() ? calculateNormalizedSquaredDistance( - mProximityInfo->getKeyIndexOf(currentChar), i) : + mProximityInfo->getKeyIndexOf(currentCodePoint), i) : NOT_A_DISTANCE_FLOAT; if (squaredDistance >= 0.0f) { mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j] = @@ -334,7 +335,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO; } if (DEBUG_PROXIMITY_CHARS) { - AKLOGI("--- Proximity (%d) = %c", j, currentChar); + AKLOGI("--- Proximity (%d) = %c", j, currentCodePoint); } } } @@ -449,7 +450,7 @@ float ProximityInfoState::getPointScore( // Sampling touch point and pushing information to vectors. // Returning if previous point is popped or not. -bool ProximityInfoState::pushTouchPoint(const int inputIndex, const int nodeChar, int x, int y, +bool ProximityInfoState::pushTouchPoint(const int inputIndex, const int nodeCodePoint, int x, int y, const int time, const bool sample, const bool isLastPoint, const float sumAngle, NearKeysDistanceMap *const currentNearKeysDistances, const NearKeysDistanceMap *const prevNearKeysDistances, @@ -458,7 +459,7 @@ bool ProximityInfoState::pushTouchPoint(const int inputIndex, const int nodeChar size_t size = mInputXs.size(); bool popped = false; - if (nodeChar < 0 && sample) { + if (nodeCodePoint < 0 && sample) { const float nearest = updateNearKeysDistances(x, y, currentNearKeysDistances); const float score = getPointScore(x, y, time, isLastPoint, nearest, sumAngle, currentNearKeysDistances, prevNearKeysDistances, prevPrevNearKeysDistances); @@ -487,8 +488,8 @@ bool ProximityInfoState::pushTouchPoint(const int inputIndex, const int nodeChar } } - if (nodeChar >= 0 && (x < 0 || y < 0)) { - const int keyId = mProximityInfo->getKeyIndexOf(nodeChar); + if (nodeCodePoint >= 0 && (x < 0 || y < 0)) { + const int keyId = mProximityInfo->getKeyIndexOf(nodeCodePoint); if (keyId >= 0) { x = mProximityInfo->getKeyCenterXOfKeyIdG(keyId); y = mProximityInfo->getKeyCenterYOfKeyIdG(keyId); @@ -543,7 +544,7 @@ float ProximityInfoState::getPointToKeyLength(const int inputIndex, const int co const int index = inputIndex * mProximityInfo->getKeyCount() + keyId; return min(mDistanceCache[index], mMaxPointToKeyLength); } - if (isSkippableChar(codePoint)) { + if (isSkippableCodePoint(codePoint)) { return 0.0f; } // If the char is not a key on the keyboard then return the max length. @@ -960,9 +961,9 @@ bool ProximityInfoState::suppressCharProbabilities(const int index0, const int i return true; } -// Get a word that is detected by tracing highest probability sequence into charBuf and returns -// probability of generating the word. -float ProximityInfoState::getHighestProbabilitySequence(uint16_t *const charBuf) const { +// Get a word that is detected by tracing highest probability sequence into codePointBuf and +// returns probability of generating the word. +float ProximityInfoState::getHighestProbabilitySequence(int *const codePointBuf) const { static const float DEMOTION_LOG_PROBABILITY = 0.3f; int index = 0; float sumLogProbability = 0.0f; @@ -980,12 +981,12 @@ float ProximityInfoState::getHighestProbabilitySequence(uint16_t *const charBuf) } } if (character != NOT_AN_INDEX) { - charBuf[index] = mProximityInfo->getCodePointOf(character); + codePointBuf[index] = mProximityInfo->getCodePointOf(character); index++; } sumLogProbability += minLogProbability; } - charBuf[index] = '\0'; + codePointBuf[index] = '\0'; return sumLogProbability; } diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h index 1a3f2869d..14fe2d3f5 100644 --- a/native/jni/src/proximity_info_state.h +++ b/native/jni/src/proximity_info_state.h @@ -43,7 +43,7 @@ class ProximityInfoState { // Defined in proximity_info_state.cpp // ///////////////////////////////////////// void initInputParams(const int pointerId, const float maxPointToKeyLength, - const ProximityInfo *proximityInfo, const int32_t *const inputCodes, + const ProximityInfo *proximityInfo, const int *const inputCodes, const int inputSize, const int *xCoordinates, const int *yCoordinates, const int *const times, const int *const pointerIds, const bool isGeometric); @@ -65,15 +65,15 @@ class ProximityInfoState { virtual ~ProximityInfoState() {} - inline unsigned short getPrimaryCharAt(const int index) const { - return getProximityCharsAt(index)[0]; + inline int getPrimaryCodePointAt(const int index) const { + return getProximityCodePointsAt(index)[0]; } - inline bool existsCharInProximityAt(const int index, const int c) const { - const int *chars = getProximityCharsAt(index); + inline bool existsCodePointInProximityAt(const int index, const int c) const { + const int *codePoints = getProximityCodePointsAt(index); int i = 0; - while (chars[i] > 0 && i < MAX_PROXIMITY_CHARS_SIZE_INTERNAL) { - if (chars[i++] == c) { + while (codePoints[i] > 0 && i < MAX_PROXIMITY_CHARS_SIZE_INTERNAL) { + if (codePoints[i++] == c) { return true; } } @@ -82,13 +82,13 @@ class ProximityInfoState { inline bool existsAdjacentProximityChars(const int index) const { if (index < 0 || index >= mInputSize) return false; - const int currentChar = getPrimaryCharAt(index); + const int currentCodePoint = getPrimaryCodePointAt(index); const int leftIndex = index - 1; - if (leftIndex >= 0 && existsCharInProximityAt(leftIndex, currentChar)) { + if (leftIndex >= 0 && existsCodePointInProximityAt(leftIndex, currentCodePoint)) { return true; } const int rightIndex = index + 1; - if (rightIndex < mInputSize && existsCharInProximityAt(rightIndex, currentChar)) { + if (rightIndex < mInputSize && existsCodePointInProximityAt(rightIndex, currentCodePoint)) { return true; } return false; @@ -106,15 +106,15 @@ class ProximityInfoState { // Notice : accented characters do not have a proximity list, so they are alone // in their list. The non-accented version of the character should be considered // "close", but not the other keys close to the non-accented version. - inline ProximityType getMatchedProximityId(const int index, - const unsigned short c, const bool checkProximityChars, int *proximityIndex = 0) const { - const int *currentChars = getProximityCharsAt(index); - const int firstChar = currentChars[0]; - const unsigned short baseLowerC = toBaseLowerCase(c); + inline ProximityType getMatchedProximityId(const int index, const int c, + const bool checkProximityChars, int *proximityIndex = 0) const { + const int *currentCodePoints = getProximityCodePointsAt(index); + const int firstCodePoint = currentCodePoints[0]; + const int baseLowerC = toBaseLowerCase(c); // The first char in the array is what user typed. If it matches right away, // that means the user typed that same char for this pos. - if (firstChar == baseLowerC || firstChar == c) { + if (firstCodePoint == baseLowerC || firstCodePoint == c) { return EQUIVALENT_CHAR; } @@ -123,14 +123,14 @@ class ProximityInfoState { // If the non-accented, lowercased version of that first character matches c, // then we have a non-accented version of the accented character the user // typed. Treat it as a close char. - if (toBaseLowerCase(firstChar) == baseLowerC) + if (toBaseLowerCase(firstCodePoint) == baseLowerC) return NEAR_PROXIMITY_CHAR; // Not an exact nor an accent-alike match: search the list of close keys int j = 1; while (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL - && currentChars[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { - const bool matched = (currentChars[j] == baseLowerC || currentChars[j] == c); + && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { + const bool matched = (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c); if (matched) { if (proximityIndex) { *proximityIndex = j; @@ -140,11 +140,12 @@ class ProximityInfoState { ++j; } if (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL - && currentChars[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { + && currentCodePoints[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { ++j; while (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL - && currentChars[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { - const bool matched = (currentChars[j] == baseLowerC || currentChars[j] == c); + && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { + const bool matched = + (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c); if (matched) { if (proximityIndex) { *proximityIndex = j; @@ -165,7 +166,7 @@ class ProximityInfoState { inputIndex * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + proximityIndex]; } - inline const unsigned short *getPrimaryInputWord() const { + inline const int *getPrimaryInputWord() const { return mPrimaryInputWord; } @@ -173,13 +174,13 @@ class ProximityInfoState { return mTouchPositionCorrectionEnabled; } - inline bool sameAsTyped(const unsigned short *word, int length) const { + inline bool sameAsTyped(const int *word, int length) const { if (length != mInputSize) { return false; } const int *inputCodes = mInputCodes; while (length--) { - if (static_cast(*inputCodes) != static_cast(*word)) { + if (*inputCodes != *word) { return false; } inputCodes += MAX_PROXIMITY_CHARS_SIZE_INTERNAL; @@ -236,7 +237,7 @@ class ProximityInfoState { // Returns angle of three points. x, y, and z are indices. float getPointsAngle(const int index0, const int index1, const int index2) const; - float getHighestProbabilitySequence(uint16_t *const charBuf) const; + float getHighestProbabilitySequence(int *const codePointBuf) const; float getProbability(const int index, const int charCode) const; @@ -255,7 +256,7 @@ class ProximityInfoState { float calculateSquaredDistanceFromSweetSpotCenter( const int keyIndex, const int inputIndex) const; - bool pushTouchPoint(const int inputIndex, const int nodeChar, int x, int y, const int time, + bool pushTouchPoint(const int inputIndex, const int nodeCodePoint, int x, int y, const int time, const bool sample, const bool isLastPoint, const float sumAngle, NearKeysDistanceMap *const currentNearKeysDistances, const NearKeysDistanceMap *const prevNearKeysDistances, @@ -269,7 +270,7 @@ class ProximityInfoState { return mInputXs.size() > 0 && mInputYs.size() > 0; } - inline const int *getProximityCharsAt(const int index) const { + inline const int *getProximityCodePointsAt(const int index) const { return mInputCodes + (index * MAX_PROXIMITY_CHARS_SIZE_INTERNAL); } @@ -322,10 +323,10 @@ class ProximityInfoState { // inputs including the current input point. std::vector mSearchKeysVector; bool mTouchPositionCorrectionEnabled; - int32_t mInputCodes[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL]; + int mInputCodes[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL]; int mNormalizedSquaredDistances[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL]; int mInputSize; - unsigned short mPrimaryInputWord[MAX_WORD_LENGTH_INTERNAL]; + int mPrimaryInputWord[MAX_WORD_LENGTH_INTERNAL]; }; } // namespace latinime #endif // LATINIME_PROXIMITY_INFO_STATE_H diff --git a/native/jni/src/terminal_attributes.h b/native/jni/src/terminal_attributes.h index e72e7e3be..fed3c7251 100644 --- a/native/jni/src/terminal_attributes.h +++ b/native/jni/src/terminal_attributes.h @@ -43,18 +43,16 @@ class TerminalAttributes { return mHasNextShortcutTarget; } - // Gets the shortcut target itself as a uint16_t string. For parameters and return value + // Gets the shortcut target itself as an int string. For parameters and return value // see BinaryFormat::getWordAtAddress. - // TODO: make the output an uint32_t* to handle the whole unicode range. - inline int getNextShortcutTarget(const int maxDepth, uint16_t *outWord, int *outFreq) { + inline int getNextShortcutTarget(const int maxDepth, int *outWord, int *outFreq) { const int shortcutFlags = BinaryFormat::getFlagsAndForwardPointer(mDict, &mPos); - mHasNextShortcutTarget = - 0 != (shortcutFlags & BinaryFormat::FLAG_ATTRIBUTE_HAS_NEXT); + mHasNextShortcutTarget = 0 != (shortcutFlags & BinaryFormat::FLAG_ATTRIBUTE_HAS_NEXT); unsigned int i; for (i = 0; i < MAX_WORD_LENGTH_INTERNAL; ++i) { const int codePoint = BinaryFormat::getCodePointAndForwardPointer(mDict, &mPos); if (NOT_A_CODE_POINT == codePoint) break; - outWord[i] = (uint16_t)codePoint; + outWord[i] = codePoint; } *outFreq = BinaryFormat::getAttributeFrequencyFromFlags(shortcutFlags); return i; diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp index f1fd1389a..dadc9c897 100644 --- a/native/jni/src/unigram_dictionary.cpp +++ b/native/jni/src/unigram_dictionary.cpp @@ -55,13 +55,13 @@ UnigramDictionary::UnigramDictionary(const uint8_t *const streamStart, int fullW UnigramDictionary::~UnigramDictionary() { } -static inline unsigned int getCodesBufferSize(const int *codes, const int codesSize) { - return static_cast(sizeof(*codes)) * codesSize; +static inline int getCodesBufferSize(const int *codes, const int codesSize) { + return sizeof(*codes) * codesSize; } -// TODO: This needs to take a const unsigned short* and not tinker with its contents -static inline void addWord(unsigned short *word, int length, int frequency, - WordsPriorityQueue *queue, int type) { +// TODO: This needs to take a const int* and not tinker with its contents +static inline void addWord(int *word, int length, int frequency, WordsPriorityQueue *queue, + int type) { queue->push(frequency, word, length, type); } @@ -171,9 +171,7 @@ void UnigramDictionary::getWordWithDigraphSuggestionsRec(ProximityInfo *proximit int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, const int *ycoordinates, const int *codes, const int codesSize, const std::map *bigramMap, const uint8_t *bigramFilter, - const bool useFullEditDistance, unsigned short *outWords, int *frequencies, - int *outputTypes) const { - + const bool useFullEditDistance, int *outWords, int *frequencies, int *outputTypes) const { WordsPriorityQueuePool queuePool(MAX_WORDS, SUB_QUEUE_MAX_WORDS, MAX_WORD_LENGTH); queuePool.clearAll(); Correction masterCorrection; @@ -218,7 +216,7 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *x AKLOGI("Returning %d words", suggestedWordsCount); /// Print the returned words for (int j = 0; j < suggestedWordsCount; ++j) { - short unsigned int *w = outWords + j * MAX_WORD_LENGTH; + int *w = outWords + j * MAX_WORD_LENGTH; char s[MAX_WORD_LENGTH]; for (int i = 0; i <= MAX_WORD_LENGTH; i++) s[i] = w[i]; (void)s; // To suppress compiler warning @@ -230,12 +228,11 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *x return suggestedWordsCount; } -void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo, - const int *xcoordinates, const int *ycoordinates, const int *codes, - const int inputSize, const std::map *bigramMap, const uint8_t *bigramFilter, - const bool useFullEditDistance, Correction *correction, - WordsPriorityQueuePool *queuePool) const { - +void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, + const int *ycoordinates, const int *codes, const int inputSize, + const std::map *bigramMap, const uint8_t *bigramFilter, + const bool useFullEditDistance, Correction *correction, WordsPriorityQueuePool *queuePool) + const { PROF_OPEN; PROF_START(0); PROF_END(0); @@ -284,7 +281,7 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo, if (queue->size() > 0) { WordsPriorityQueue::SuggestedWord *sw = queue->top(); const int score = sw->mScore; - const unsigned short *word = sw->mWord; + const int *word = sw->mWord; const int wordLength = sw->mWordLength; float ns = Correction::RankingAlgorithm::calcNormalizedScore( correction->getPrimaryInputWord(), i, word, wordLength, score); @@ -303,7 +300,7 @@ void UnigramDictionary::initSuggestions(ProximityInfo *proximityInfo, const int Correction *correction) const { if (DEBUG_DICT) { AKLOGI("initSuggest"); - DUMP_WORD_INT(codes, inputSize); + DUMP_WORD(codes, inputSize); } correction->initInputParams(proximityInfo, codes, inputSize, xCoordinates, yCoordinates); const int maxDepth = min(inputSize * MAX_DEPTH_MULTIPLIER, MAX_WORD_LENGTH); @@ -376,7 +373,7 @@ inline void UnigramDictionary::onTerminal(const int probability, const bool addToSubQueue = inputIndex < SUB_QUEUE_MAX_COUNT; int wordLength; - unsigned short *wordPointer; + int *wordPointer; if ((currentWordIndex == FIRST_WORD_INDEX) && addToMasterQueue) { WordsPriorityQueue *masterQueue = queuePool->getMasterQueue(); @@ -404,7 +401,7 @@ inline void UnigramDictionary::onTerminal(const int probability, // so that the insert order is protected inside the queue for words // with the same score. For the moment we use -1 to make sure the shortcut will // never be in front of the word. - uint16_t shortcutTarget[MAX_WORD_LENGTH_INTERNAL]; + int shortcutTarget[MAX_WORD_LENGTH_INTERNAL]; int shortcutFrequency; const int shortcutTargetStringLength = iterator.getNextShortcutTarget( MAX_WORD_LENGTH_INTERNAL, shortcutTarget, &shortcutFrequency); @@ -444,7 +441,7 @@ int UnigramDictionary::getSubStringSuggestion( const bool hasAutoCorrectionCandidate, const int currentWordIndex, const int inputWordStartPos, const int inputWordLength, const int outputWordStartPos, const bool isSpaceProximity, int *freqArray, - int *wordLengthArray, unsigned short *outputWord, int *outputWordLength) const { + int *wordLengthArray, int *outputWord, int *outputWordLength) const { if (inputWordLength > MULTIPLE_WORDS_SUGGESTION_MAX_WORD_LENGTH) { return FLAG_MULTIPLE_SUGGEST_ABORT; } @@ -487,13 +484,13 @@ int UnigramDictionary::getSubStringSuggestion( // TODO: Remove the safety net above // ////////////////////////////////////////////// - unsigned short *tempOutputWord = 0; + int *tempOutputWord = 0; int nextWordLength = 0; // TODO: Optimize init suggestion initSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, inputSize, correction); - unsigned short word[MAX_WORD_LENGTH_INTERNAL]; + int word[MAX_WORD_LENGTH_INTERNAL]; int freq = getMostFrequentWordLike( inputWordStartPos, inputWordLength, correction, word); if (freq > 0) { @@ -592,7 +589,7 @@ void UnigramDictionary::getMultiWordsSuggestionRec(ProximityInfo *proximityInfo, const bool useFullEditDistance, const int inputSize, Correction *correction, WordsPriorityQueuePool *queuePool, const bool hasAutoCorrectionCandidate, const int startInputPos, const int startWordIndex, const int outputWordLength, - int *freqArray, int *wordLengthArray, unsigned short *outputWord) const { + int *freqArray, int *wordLengthArray, int *outputWord) const { if (startWordIndex >= (MULTIPLE_WORDS_SUGGESTION_MAX_WORDS - 1)) { // Return if the last word index return; @@ -678,7 +675,7 @@ void UnigramDictionary::getSplitMultipleWordsSuggestions(ProximityInfo *proximit } // Allocating fixed length array on stack - unsigned short outputWord[MAX_WORD_LENGTH]; + int outputWord[MAX_WORD_LENGTH]; int freqArray[MULTIPLE_WORDS_SUGGESTION_MAX_WORDS]; int wordLengthArray[MULTIPLE_WORDS_SUGGESTION_MAX_WORDS]; const int outputWordLength = 0; @@ -693,11 +690,11 @@ void UnigramDictionary::getSplitMultipleWordsSuggestions(ProximityInfo *proximit // Wrapper for getMostFrequentWordLikeInner, which matches it to the previous // interface. inline int UnigramDictionary::getMostFrequentWordLike(const int startInputIndex, - const int inputSize, Correction *correction, unsigned short *word) const { - uint16_t inWord[inputSize]; + const int inputSize, Correction *correction, int *word) const { + int inWord[inputSize]; for (int i = 0; i < inputSize; ++i) { - inWord[i] = (uint16_t)correction->getPrimaryCharAt(startInputIndex + i); + inWord[i] = correction->getPrimaryCodePointAt(startInputIndex + i); } return getMostFrequentWordLikeInner(inWord, inputSize, word); } @@ -715,14 +712,14 @@ inline int UnigramDictionary::getMostFrequentWordLike(const int startInputIndex, // In and out parameters may point to the same location. This function takes care // not to use any input parameters after it wrote into its outputs. static inline bool testCharGroupForContinuedLikeness(const uint8_t flags, - const uint8_t *const root, const int startPos, const uint16_t *const inWord, - const int startInputIndex, const int inputSize, int32_t *outNewWord, int *outInputIndex, + const uint8_t *const root, const int startPos, const int *const inWord, + const int startInputIndex, const int inputSize, int *outNewWord, int *outInputIndex, int *outPos) { const bool hasMultipleChars = (0 != (BinaryFormat::FLAG_HAS_MULTIPLE_CHARS & flags)); int pos = startPos; - int32_t codePoint = BinaryFormat::getCodePointAndForwardPointer(root, &pos); - int32_t baseChar = toBaseLowerCase(codePoint); - const uint16_t wChar = toBaseLowerCase(inWord[startInputIndex]); + int codePoint = BinaryFormat::getCodePointAndForwardPointer(root, &pos); + int baseChar = toBaseLowerCase(codePoint); + const int wChar = toBaseLowerCase(inWord[startInputIndex]); if (baseChar != wChar) { *outPos = hasMultipleChars ? BinaryFormat::skipOtherCharacters(root, pos) : pos; @@ -753,8 +750,8 @@ static inline bool testCharGroupForContinuedLikeness(const uint8_t flags, // It will compare the frequency to the max frequency, and if greater, will // copy the word into the output buffer. In output value maxFreq, it will // write the new maximum frequency if it changed. -static inline void onTerminalWordLike(const int freq, int32_t *newWord, const int length, - short unsigned int *outWord, int *maxFreq) { +static inline void onTerminalWordLike(const int freq, int *newWord, const int length, int *outWord, + int *maxFreq) { if (freq > *maxFreq) { for (int q = 0; q < length; ++q) { outWord[q] = newWord[q]; @@ -766,9 +763,9 @@ static inline void onTerminalWordLike(const int freq, int32_t *newWord, const in // Will find the highest frequency of the words like the one passed as an argument, // that is, everything that only differs by case/accents. -int UnigramDictionary::getMostFrequentWordLikeInner(const uint16_t *const inWord, - const int inputSize, short unsigned int *outWord) const { - int32_t newWord[MAX_WORD_LENGTH_INTERNAL]; +int UnigramDictionary::getMostFrequentWordLikeInner(const int *const inWord, const int inputSize, + int *outWord) const { + int newWord[MAX_WORD_LENGTH_INTERNAL]; int depth = 0; int maxFreq = -1; const uint8_t *const root = DICT_ROOT; @@ -828,7 +825,7 @@ int UnigramDictionary::getMostFrequentWordLikeInner(const uint16_t *const inWord return maxFreq; } -int UnigramDictionary::getFrequency(const int32_t *const inWord, const int length) const { +int UnigramDictionary::getFrequency(const int *const inWord, const int length) const { const uint8_t *const root = DICT_ROOT; int pos = BinaryFormat::getTerminalPosition(root, inWord, length, false /* forceLowerCaseSearch */); @@ -853,8 +850,7 @@ int UnigramDictionary::getFrequency(const int32_t *const inWord, const int lengt } // TODO: remove this function. -int UnigramDictionary::getBigramPosition(int pos, unsigned short *word, int offset, - int length) const { +int UnigramDictionary::getBigramPosition(int pos, int *word, int offset, int length) const { return -1; } @@ -900,7 +896,7 @@ inline bool UnigramDictionary::processCurrentNode(const int initialPos, // else if FLAG_IS_TERMINAL: the frequency // else if MASK_GROUP_ADDRESS_TYPE is not NONE: the children address // Note that you can't have a node that both is not a terminal and has no children. - int32_t c = BinaryFormat::getCodePointAndForwardPointer(DICT_ROOT, &pos); + int c = BinaryFormat::getCodePointAndForwardPointer(DICT_ROOT, &pos); assert(NOT_A_CODE_POINT != c); // We are going to loop through each character and make it look like it's a different @@ -914,7 +910,7 @@ inline bool UnigramDictionary::processCurrentNode(const int initialPos, // We prefetch the next char. If 'c' is the last char of this node, we will have // NOT_A_CODE_POINT in the next char. From this we can decide whether this virtual node // should behave as a terminal or not and whether we have children. - const int32_t nextc = hasMultipleChars + const int nextc = hasMultipleChars ? BinaryFormat::getCodePointAndForwardPointer(DICT_ROOT, &pos) : NOT_A_CODE_POINT; const bool isLastChar = (NOT_A_CODE_POINT == nextc); // If there are more chars in this nodes, then this virtual node is not a terminal. diff --git a/native/jni/src/unigram_dictionary.h b/native/jni/src/unigram_dictionary.h index 244d78d8c..764900739 100644 --- a/native/jni/src/unigram_dictionary.h +++ b/native/jni/src/unigram_dictionary.h @@ -41,12 +41,12 @@ class UnigramDictionary { static const int FLAG_MULTIPLE_SUGGEST_CONTINUE = 2; UnigramDictionary(const uint8_t *const streamStart, int fullWordMultiplier, int maxWordLength, int maxWords, const unsigned int flags); - int getFrequency(const int32_t *const inWord, const int length) const; - int getBigramPosition(int pos, unsigned short *word, int offset, int length) const; + int getFrequency(const int *const inWord, const int length) const; + int getBigramPosition(int pos, int *word, int offset, int length) const; int getSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, const int *ycoordinates, const int *codes, const int codesSize, const std::map *bigramMap, const uint8_t *bigramFilter, - const bool useFullEditDistance, unsigned short *outWords, int *frequencies, + const bool useFullEditDistance, int *outWords, int *frequencies, int *outputTypes) const; virtual ~UnigramDictionary(); @@ -93,9 +93,9 @@ class UnigramDictionary { int *newChildPosition, int *nextSiblingPosition, WordsPriorityQueuePool *queuePool, const int currentWordIndex) const; int getMostFrequentWordLike(const int startInputIndex, const int inputSize, - Correction *correction, unsigned short *word) const; - int getMostFrequentWordLikeInner(const uint16_t *const inWord, const int inputSize, - short unsigned int *outWord) const; + Correction *correction, int *word) const; + int getMostFrequentWordLikeInner(const int *const inWord, const int inputSize, + int *outWord) const; int getSubStringSuggestion( ProximityInfo *proximityInfo, const int *xcoordinates, const int *ycoordinates, const int *codes, const bool useFullEditDistance, Correction *correction, @@ -103,14 +103,13 @@ class UnigramDictionary { const bool hasAutoCorrectionCandidate, const int currentWordIndex, const int inputWordStartPos, const int inputWordLength, const int outputWordStartPos, const bool isSpaceProximity, int *freqArray, - int *wordLengthArray, unsigned short *outputWord, int *outputWordLength) const; - void getMultiWordsSuggestionRec(ProximityInfo *proximityInfo, - const int *xcoordinates, const int *ycoordinates, const int *codes, - const bool useFullEditDistance, const int inputSize, - Correction *correction, WordsPriorityQueuePool *queuePool, + int *wordLengthArray, int *outputWord, int *outputWordLength) const; + void getMultiWordsSuggestionRec(ProximityInfo *proximityInfo, const int *xcoordinates, + const int *ycoordinates, const int *codes, const bool useFullEditDistance, + const int inputSize, Correction *correction, WordsPriorityQueuePool *queuePool, const bool hasAutoCorrectionCandidate, const int startPos, const int startWordIndex, const int outputWordLength, int *freqArray, int *wordLengthArray, - unsigned short *outputWord) const; + int *outputWord) const; const uint8_t *const DICT_ROOT; const int MAX_WORD_LENGTH; diff --git a/native/jni/src/words_priority_queue.h b/native/jni/src/words_priority_queue.h index 19efa5da3..ac384dd69 100644 --- a/native/jni/src/words_priority_queue.h +++ b/native/jni/src/words_priority_queue.h @@ -30,15 +30,15 @@ class WordsPriorityQueue { class SuggestedWord { public: int mScore; - unsigned short mWord[MAX_WORD_LENGTH_INTERNAL]; + int mWord[MAX_WORD_LENGTH_INTERNAL]; int mWordLength; bool mUsed; int mType; - void setParams(int score, unsigned short *word, int wordLength, int type) { + void setParams(int score, int *word, int wordLength, int type) { mScore = score; mWordLength = wordLength; - memcpy(mWord, word, sizeof(unsigned short) * wordLength); + memcpy(mWord, word, sizeof(int) * wordLength); mUsed = true; mType = type; } @@ -57,9 +57,9 @@ class WordsPriorityQueue { delete[] mSuggestedWords; } - void push(int score, unsigned short *word, int wordLength, int type) { + void push(int score, int *word, int wordLength, int type) { SuggestedWord *sw = 0; - if (mSuggestions.size() >= MAX_WORDS) { + if (size() >= MAX_WORDS) { sw = mSuggestions.top(); const int minScore = sw->mScore; if (minScore >= score) { @@ -94,11 +94,10 @@ class WordsPriorityQueue { return sw; } - int outputSuggestions(const unsigned short *before, const int beforeLength, - int *frequencies, unsigned short *outputChars, int* outputTypes) { + int outputSuggestions(const int *before, const int beforeLength, int *frequencies, + int *outputCodePoints, int* outputTypes) { mHighestSuggestedWord = 0; - const unsigned int size = min( - MAX_WORDS, static_cast(mSuggestions.size())); + const int size = min(MAX_WORDS, static_cast(mSuggestions.size())); SuggestedWord *swBuffer[size]; int index = size - 1; while (!mSuggestions.empty() && index >= 0) { @@ -113,9 +112,9 @@ class WordsPriorityQueue { } if (size >= 2) { SuggestedWord *nsMaxSw = 0; - unsigned int maxIndex = 0; + int maxIndex = 0; float maxNs = 0; - for (unsigned int i = 0; i < size; ++i) { + for (int i = 0; i < size; ++i) { SuggestedWord *tempSw = swBuffer[i]; if (!tempSw) { continue; @@ -132,17 +131,17 @@ class WordsPriorityQueue { swBuffer[0] = nsMaxSw; } } - for (unsigned int i = 0; i < size; ++i) { + for (int i = 0; i < size; ++i) { SuggestedWord *sw = swBuffer[i]; if (!sw) { AKLOGE("SuggestedWord is null %d", i); continue; } - const unsigned int wordLength = sw->mWordLength; - unsigned short *targetAddress = outputChars + i * MAX_WORD_LENGTH; + const int wordLength = sw->mWordLength; + int *targetAddress = outputCodePoints + i * MAX_WORD_LENGTH; frequencies[i] = sw->mScore; outputTypes[i] = sw->mType; - memcpy(targetAddress, sw->mWord, wordLength * sizeof(unsigned short)); + memcpy(targetAddress, sw->mWord, wordLength * sizeof(int)); if (wordLength < MAX_WORD_LENGTH) { targetAddress[wordLength] = 0; } @@ -152,7 +151,7 @@ class WordsPriorityQueue { } int size() const { - return mSuggestions.size(); + return static_cast(mSuggestions.size()); } void clear() { @@ -175,13 +174,13 @@ class WordsPriorityQueue { DUMP_WORD(mHighestSuggestedWord->mWord, mHighestSuggestedWord->mWordLength); } - float getHighestNormalizedScore(const unsigned short *before, const int beforeLength, - unsigned short **outWord, int *outScore, int *outLength) { + float getHighestNormalizedScore(const int *before, const int beforeLength, int **outWord, + int *outScore, int *outLength) { if (!mHighestSuggestedWord) { return 0.0; } - return getNormalizedScore( - mHighestSuggestedWord, before, beforeLength, outWord, outScore, outLength); + return getNormalizedScore(mHighestSuggestedWord, before, beforeLength, outWord, outScore, + outLength); } private: @@ -192,9 +191,8 @@ class WordsPriorityQueue { } }; - SuggestedWord *getFreeSuggestedWord(int score, unsigned short *word, - int wordLength, int type) { - for (unsigned int i = 0; i < MAX_WORD_LENGTH; ++i) { + SuggestedWord *getFreeSuggestedWord(int score, int *word, int wordLength, int type) { + for (int i = 0; i < MAX_WORD_LENGTH; ++i) { if (!mSuggestedWords[i].mUsed) { mSuggestedWords[i].setParams(score, word, wordLength, type); return &mSuggestedWords[i]; @@ -203,10 +201,10 @@ class WordsPriorityQueue { return 0; } - static float getNormalizedScore(SuggestedWord *sw, const unsigned short *before, - const int beforeLength, unsigned short **outWord, int *outScore, int *outLength) { + static float getNormalizedScore(SuggestedWord *sw, const int *before, const int beforeLength, + int **outWord, int *outScore, int *outLength) { const int score = sw->mScore; - unsigned short *word = sw->mWord; + int *word = sw->mWord; const int wordLength = sw->mWordLength; if (outScore) { *outScore = score; @@ -217,15 +215,15 @@ class WordsPriorityQueue { if (outLength) { *outLength = wordLength; } - return Correction::RankingAlgorithm::calcNormalizedScore( - before, beforeLength, word, wordLength, score); + return Correction::RankingAlgorithm::calcNormalizedScore(before, beforeLength, word, + wordLength, score); } typedef std::priority_queue, wordComparator> Suggestions; Suggestions mSuggestions; - const unsigned int MAX_WORDS; - const unsigned int MAX_WORD_LENGTH; + const int MAX_WORDS; + const int MAX_WORD_LENGTH; SuggestedWord *mSuggestedWords; SuggestedWord *mHighestSuggestedWord; }; -- cgit v1.2.3-83-g751a From 20dd1bc090abdd3e88855fe54b1865949aa1168d Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Mon, 29 Oct 2012 15:14:20 +0900 Subject: Cosmetic source code formating change Change-Id: I3a53b49afab70dfb13f12027070635da6001eb79 --- .../com/android/inputmethod/keyboard/Keyboard.java | 2 - .../inputmethod/keyboard/MainKeyboardView.java | 82 ++++++++++++++-------- .../com/android/inputmethod/latin/Constants.java | 1 - 3 files changed, 51 insertions(+), 34 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index dd2e3d392..a1b1f5dad 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -24,8 +24,6 @@ import com.android.inputmethod.keyboard.internal.KeyboardParams; import com.android.inputmethod.latin.CollectionUtils; import com.android.inputmethod.latin.Constants; - - /** * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard * consists of rows of keys. diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index 4efc526bf..84dada7f1 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -204,7 +204,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack private void startKeyRepeatTimer(final PointerTracker tracker, final long delay) { final Key key = tracker.getKey(); - if (key == null) return; + if (key == null) { + return; + } sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, key.mCode, 0, tracker), delay); } @@ -409,7 +411,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } private ObjectAnimator loadObjectAnimator(final int resId, final Object target) { - if (resId == 0) return null; + if (resId == 0) { + return null; + } final ObjectAnimator animator = (ObjectAnimator)AnimatorInflater.loadAnimator( getContext(), resId); if (animator != null) { @@ -557,21 +561,25 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } // Check if we are already displaying popup panel. - if (mMoreKeysPanel != null) + if (mMoreKeysPanel != null) { return false; - if (parentKey == null) + } + if (parentKey == null) { return false; + } return onLongPress(parentKey, tracker); } // This default implementation returns a more keys panel. protected MoreKeysPanel onCreateMoreKeysPanel(final Key parentKey) { - if (parentKey.mMoreKeys == null) + if (parentKey.mMoreKeys == null) { return null; + } final View container = LayoutInflater.from(getContext()).inflate(mMoreKeysLayout, null); - if (container == null) + if (container == null) { throw new NullPointerException(); + } final MoreKeysKeyboardView moreKeysKeyboardView = (MoreKeysKeyboardView)container.findViewById(R.id.more_keys_keyboard_view); @@ -632,8 +640,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack MoreKeysPanel moreKeysPanel = mMoreKeysPanelCache.get(parentKey); if (moreKeysPanel == null) { moreKeysPanel = onCreateMoreKeysPanel(parentKey); - if (moreKeysPanel == null) + if (moreKeysPanel == null) { return false; + } mMoreKeysPanelCache.put(parentKey, moreKeysPanel); } if (mMoreKeysWindow == null) { @@ -669,9 +678,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack public boolean isInSlidingKeyInput() { if (mMoreKeysPanel != null) { return true; - } else { - return PointerTracker.isAnyInSlidingKeyInput(); } + return PointerTracker.isAnyInSlidingKeyInput(); } public int getPointerCount() { @@ -844,14 +852,14 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack @Override public boolean dismissMoreKeysPanel() { - if (mMoreKeysWindow != null && mMoreKeysWindow.isShowing()) { - mMoreKeysWindow.dismiss(); - mMoreKeysPanel = null; - mMoreKeysPanelPointerTrackerId = -1; - dimEntireKeyboard(false); - return true; + if (mMoreKeysWindow == null || !mMoreKeysWindow.isShowing()) { + return false; } - return false; + mMoreKeysWindow.dismiss(); + mMoreKeysPanel = null; + mMoreKeysPanelPointerTrackerId = -1; + dimEntireKeyboard(false); + return true; } /** @@ -874,16 +882,22 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack public void updateShortcutKey(final boolean available) { final Keyboard keyboard = getKeyboard(); - if (keyboard == null) return; + if (keyboard == null) { + return; + } final Key shortcutKey = keyboard.getKey(Constants.CODE_SHORTCUT); - if (shortcutKey == null) return; + if (shortcutKey == null) { + return; + } shortcutKey.setEnabled(available); invalidateKey(shortcutKey); } private void updateAltCodeKeyWhileTyping() { final Keyboard keyboard = getKeyboard(); - if (keyboard == null) return; + if (keyboard == null) { + return; + } for (final Key key : keyboard.mAltCodeKeysWhileTyping) { invalidateKey(key); } @@ -913,7 +927,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } public void updateAutoCorrectionState(final boolean isAutoCorrection) { - if (!mAutoCorrectionSpacebarLedEnabled) return; + if (!mAutoCorrectionSpacebarLedEnabled) { + return; + } mAutoCorrectionSpacebarLedOn = isAutoCorrection; invalidateKey(mSpaceKey); } @@ -941,10 +957,14 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack private boolean fitsTextIntoWidth(final int width, final String text, final Paint paint) { paint.setTextScaleX(1.0f); final float textWidth = getLabelWidth(text, paint); - if (textWidth < width) return true; + if (textWidth < width) { + return true; + } final float scaleX = width / textWidth; - if (scaleX < MINIMUM_XSCALE_OF_LANGUAGE_NAME) return false; + if (scaleX < MINIMUM_XSCALE_OF_LANGUAGE_NAME) { + return false; + } paint.setTextScaleX(scaleX); return getLabelWidth(text, paint) < width; @@ -954,19 +974,19 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack private String layoutLanguageOnSpacebar(final Paint paint, final InputMethodSubtype subtype, final int width) { // Choose appropriate language name to fit into the width. - String text = getFullDisplayName(subtype, getResources()); - if (fitsTextIntoWidth(width, text, paint)) { - return text; + final String fullText = getFullDisplayName(subtype, getResources()); + if (fitsTextIntoWidth(width, fullText, paint)) { + return fullText; } - text = getMiddleDisplayName(subtype); - if (fitsTextIntoWidth(width, text, paint)) { - return text; + final String middleText = getMiddleDisplayName(subtype); + if (fitsTextIntoWidth(width, middleText, paint)) { + return middleText; } - text = getShortDisplayName(subtype); - if (fitsTextIntoWidth(width, text, paint)) { - return text; + final String shortText = getShortDisplayName(subtype); + if (fitsTextIntoWidth(width, shortText, paint)) { + return shortText; } return ""; diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java index fa6ff1848..1a93f7b1e 100644 --- a/java/src/com/android/inputmethod/latin/Constants.java +++ b/java/src/com/android/inputmethod/latin/Constants.java @@ -16,7 +16,6 @@ package com.android.inputmethod.latin; - public final class Constants { public static final class Color { /** -- cgit v1.2.3-83-g751a From 24ab8055aaae75bcb80c686efc2046a301ebb6ad Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 1 Nov 2012 12:32:33 +0900 Subject: Move isInvalidCordinates() method to Constants class Change-Id: Iad1464c299ad6055af1db1ff7978e5cd9a14750f --- .../com/android/inputmethod/keyboard/KeyboardActionListener.java | 8 -------- java/src/com/android/inputmethod/latin/Constants.java | 7 ++++++- java/src/com/android/inputmethod/latin/LatinIME.java | 9 ++++----- 3 files changed, 10 insertions(+), 14 deletions(-) (limited to 'java/src/com/android/inputmethod/latin') diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java index e7a4e82a2..b612f0927 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java @@ -112,13 +112,5 @@ public interface KeyboardActionListener { public boolean onCustomRequest(int requestCode) { return false; } - - // TODO: Remove this method when the vertical correction is removed. - public static boolean isInvalidCoordinate(final int coordinate) { - // Detect {@link Constants#NOT_A_COORDINATE}, - // {@link Constants#SUGGESTION_STRIP_COORDINATE}, and - // {@link Constants#SPELL_CHECKER_COORDINATE}. - return coordinate < 0; - } } } diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java index fa6ff1848..152fd569d 100644 --- a/java/src/com/android/inputmethod/latin/Constants.java +++ b/java/src/com/android/inputmethod/latin/Constants.java @@ -137,11 +137,16 @@ public final class Constants { public static final int NOT_A_CODE = -1; - // See {@link KeyboardActionListener.Adapter#isInvalidCoordinate(int)}. public static final int NOT_A_COORDINATE = -1; public static final int SUGGESTION_STRIP_COORDINATE = -2; public static final int SPELL_CHECKER_COORDINATE = -3; + public static boolean isValidCoordinate(final int coordinate) { + // Detect {@link NOT_A_COORDINATE}, {@link SUGGESTION_STRIP_COORDINATE}, + // and {@link SPELL_CHECKER_COORDINATE}. + return coordinate >= 0; + } + /** * Some common keys code. Must be positive. */ diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index c66ff9504..2af7b1d61 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1741,15 +1741,14 @@ public final class LatinIME extends InputMethodService implements KeyboardAction } if (isComposingWord) { final int keyX, keyY; - if (KeyboardActionListener.Adapter.isInvalidCoordinate(x) - || KeyboardActionListener.Adapter.isInvalidCoordinate(y)) { - keyX = x; - keyY = y; - } else { + if (Constants.isValidCoordinate(x) && Constants.isValidCoordinate(y)) { final KeyDetector keyDetector = mKeyboardSwitcher.getMainKeyboardView().getKeyDetector(); keyX = keyDetector.getTouchX(x); keyY = keyDetector.getTouchY(y); + } else { + keyX = x; + keyY = y; } mWordComposer.add(primaryCode, keyX, keyY); // If it's the first letter, make note of auto-caps state -- cgit v1.2.3-83-g751a