Merge "Add a relevant suggestion to period-checkable requests"
diff --git a/dictionaries/es_wordlist.combined.gz b/dictionaries/es_wordlist.combined.gz
index c0a5264..41a914c 100644
--- a/dictionaries/es_wordlist.combined.gz
+++ b/dictionaries/es_wordlist.combined.gz
Binary files differ
diff --git a/java/res/raw/main_es.dict b/java/res/raw/main_es.dict
index 0911b70..3c99e73 100644
--- a/java/res/raw/main_es.dict
+++ b/java/res/raw/main_es.dict
Binary files differ
diff --git a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java
index 3925fc6..7a945e3 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.support.v4.view.AccessibilityDelegateCompat;
 import android.support.v4.view.ViewCompat;
-import android.support.v4.view.accessibility.AccessibilityEventCompat;
 import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
 import android.util.Log;
 import android.view.MotionEvent;
@@ -31,7 +30,6 @@
 import com.android.inputmethod.keyboard.KeyDetector;
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.KeyboardView;
-import com.android.inputmethod.keyboard.PointerTracker;
 
 /**
  * This class represents a delegate that can be registered in a class that extends
@@ -264,33 +262,16 @@
     }
 
     /**
-     * Simulating a touch event by injecting a synthesized touch event into {@link PointerTracker}.
+     * Simulating a touch event by injecting a synthesized touch event into {@link KeyboardView}.
      *
      * @param touchAction The action of the synthesizing touch event.
      * @param hoverEvent The base hover event from that the touch event is synthesized.
      */
     protected void simulateTouchEvent(final int touchAction, final MotionEvent hoverEvent) {
-        final MotionEvent touchEvent = synthesizeTouchEvent(touchAction, hoverEvent);
-        final int actionIndex = touchEvent.getActionIndex();
-        final int pointerId = touchEvent.getPointerId(actionIndex);
-        final PointerTracker tracker = PointerTracker.getPointerTracker(pointerId);
-        tracker.processMotionEvent(touchEvent, mKeyDetector);
-        touchEvent.recycle();
-    }
-
-    /**
-     * Synthesize a touch event from a hover event.
-     *
-     * @param touchAction The action of the synthesizing touch event.
-     * @param hoverEvent The base hover event from that the touch event is synthesized.
-     * @return The synthesized touch event of <code>touchAction</code> that has pointer information
-     * of <code>event</code>.
-     */
-    protected static MotionEvent synthesizeTouchEvent(final int touchAction,
-            final MotionEvent hoverEvent) {
         final MotionEvent touchEvent = MotionEvent.obtain(hoverEvent);
         touchEvent.setAction(touchAction);
-        return touchEvent;
+        mKeyboardView.onTouchEvent(touchEvent);
+        touchEvent.recycle();
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java
index 61d066a..328d9ec 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java
@@ -68,7 +68,7 @@
     /** The virtual view identifier for the hovering node. */
     private int mHoveringNodeId = UNDEFINED;
 
-    /** The current keyboard view. */
+    /** The keyboard view to provide an accessibility node info. */
     private final KeyboardView mKeyboardView;
 
     /** The current keyboard. */
diff --git a/java/src/com/android/inputmethod/accessibility/MoreSuggestionsAccessibilityDelegate.java b/java/src/com/android/inputmethod/accessibility/MoreSuggestionsAccessibilityDelegate.java
index dfc8661..941bac1 100644
--- a/java/src/com/android/inputmethod/accessibility/MoreSuggestionsAccessibilityDelegate.java
+++ b/java/src/com/android/inputmethod/accessibility/MoreSuggestionsAccessibilityDelegate.java
@@ -28,9 +28,11 @@
         super(moreKeysKeyboardView, keyDetector);
     }
 
+    // TODO: Remove redundant override method.
     @Override
     protected void simulateTouchEvent(final int touchAction, final MotionEvent hoverEvent) {
-        final MotionEvent touchEvent = synthesizeTouchEvent(touchAction, hoverEvent);
+        final MotionEvent touchEvent = MotionEvent.obtain(hoverEvent);
+        touchEvent.setAction(touchAction);
         mKeyboardView.onTouchEvent(touchEvent);
         touchEvent.recycle();
     }
diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java
index 8010a3e..0634040 100644
--- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java
@@ -65,9 +65,11 @@
             super(keyboardView, keyDetector);
         }
 
+        // TODO: Remove redundant override method.
         @Override
         protected void simulateTouchEvent(int touchAction, MotionEvent hoverEvent) {
-            final MotionEvent touchEvent = synthesizeTouchEvent(touchAction, hoverEvent);
+            final MotionEvent touchEvent = MotionEvent.obtain(hoverEvent);
+            touchEvent.setAction(touchAction);
             mKeyboardView.onTouchEvent(touchEvent);
             touchEvent.recycle();
         }
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 692c03a..e43db35 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -126,16 +126,17 @@
         final boolean didRemoveTypedWord =
                 SuggestedWordInfo.removeDups(typedWord, suggestionsContainer);
 
+        final SuggestedWordInfo firstSuggestedWordInfo;
         final String whitelistedWord;
         if (suggestionsContainer.isEmpty()) {
+            firstSuggestedWordInfo = null;
             whitelistedWord = null;
         } else {
-            final SuggestedWordInfo firstSuggestedWordInfo = suggestionsContainer.get(0);
-            final String firstSuggestion = firstSuggestedWordInfo.mWord;
+            firstSuggestedWordInfo = suggestionsContainer.get(0);
             if (!firstSuggestedWordInfo.isKindOf(SuggestedWordInfo.KIND_WHITELIST)) {
                 whitelistedWord = null;
             } else {
-                whitelistedWord = firstSuggestion;
+                whitelistedWord = firstSuggestedWordInfo.mWord;
             }
         }
 
@@ -151,10 +152,10 @@
         // the current settings. It may also be useful to know, when the setting is off, whether
         // the word *would* have been auto-corrected.
         if (!isCorrectionEnabled || !allowsToBeAutoCorrected || isPrediction
-                || suggestionResults.isEmpty() || wordComposer.hasDigits()
+                || null == firstSuggestedWordInfo || wordComposer.hasDigits()
                 || wordComposer.isMostlyCaps() || wordComposer.isResumed()
                 || !mDictionaryFacilitator.hasInitializedMainDictionary()
-                || suggestionResults.first().isKindOf(SuggestedWordInfo.KIND_SHORTCUT)) {
+                || firstSuggestedWordInfo.isKindOf(SuggestedWordInfo.KIND_SHORTCUT)) {
             // If we don't have a main dictionary, we never want to auto-correct. The reason for
             // this is, the user may have a contact whose name happens to match a valid word in
             // their language, and it will unexpectedly auto-correct. For example, if the user
@@ -166,7 +167,7 @@
             hasAutoCorrection = false;
         } else {
             hasAutoCorrection = AutoCorrectionUtils.suggestionExceedsAutoCorrectionThreshold(
-                    suggestionResults.first(), consideredWord, mAutoCorrectionThreshold);
+                    firstSuggestedWordInfo, consideredWord, mAutoCorrectionThreshold);
         }
 
         if (!TextUtils.isEmpty(typedWord)) {
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
index 528d500..9f9bff5 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
@@ -51,6 +51,7 @@
         super(context, attrs, defStyle);
     }
 
+    // TODO: Remove redundant override method.
     @Override
     public void setKeyboard(final Keyboard keyboard) {
         super.setKeyboard(keyboard);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
index 4da339b..1d202c3 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
@@ -77,30 +77,6 @@
     return dictBuffers->flush(dirPath);
 }
 
-/* static */ bool DictFileWritingUtils::flushAllHeaderAndBodyToFile(const char *const filePath,
-        BufferWithExtendableBuffer *const dictHeader, BufferWithExtendableBuffer *const dictBody) {
-    const int tmpFileNameBufSize = FileUtils::getFilePathWithSuffixBufSize(filePath,
-            TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE);
-    // Name of a temporary file used for writing that is a connected string of original name and
-    // TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE.
-    char tmpFileName[tmpFileNameBufSize];
-    FileUtils::getFilePathWithSuffix(filePath, TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE,
-            tmpFileNameBufSize, tmpFileName);
-    if (!DictFileWritingUtils::flushBufferToFile(tmpFileName, dictHeader)) {
-        AKLOGE("Dictionary header cannot be written to %s.", tmpFileName);
-        return false;
-    }
-    if (!DictFileWritingUtils::flushBufferToFile(tmpFileName, dictBody)) {
-        AKLOGE("Dictionary structure cannot be written to %s.", tmpFileName);
-        return false;
-    }
-    if (rename(tmpFileName, filePath) != 0) {
-        AKLOGE("Dictionary file %s cannot be renamed to %s", tmpFileName, filePath);;
-        return false;
-    }
-    return true;
-}
-
 /* static */ bool DictFileWritingUtils::flushBufferToFileWithSuffix(const char *const basePath,
         const char *const suffix, const BufferWithExtendableBuffer *const buffer) {
     const int filePathBufSize = FileUtils::getFilePathWithSuffixBufSize(basePath, suffix);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h
index 5df5856..0dd1256 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h
@@ -35,10 +35,6 @@
             const std::vector<int> localeAsCodePointVector,
             const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap);
 
-    static bool flushAllHeaderAndBodyToFile(const char *const filePath,
-            BufferWithExtendableBuffer *const dictHeader,
-            BufferWithExtendableBuffer *const dictBody);
-
     static bool flushBufferToFileWithSuffix(const char *const basePath, const char *const suffix,
             const BufferWithExtendableBuffer *const buffer);