Merge "Implement a part of ver 3 dictionary reading methods."
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
index 6a900b4..e153107 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
@@ -178,42 +178,43 @@
 
     private Keyboard getKeyboard(final ElementParams elementParams, final KeyboardId id) {
         final SoftReference<Keyboard> ref = sKeyboardCache.get(id);
-        Keyboard keyboard = (ref == null) ? null : ref.get();
-        if (keyboard == null) {
-            final KeyboardBuilder<KeyboardParams> builder =
-                    new KeyboardBuilder<KeyboardParams>(mContext, new KeyboardParams());
-            if (id.isAlphabetKeyboard()) {
-                builder.setAutoGenerate(sKeysCache);
-            }
-            final int keyboardXmlId = elementParams.mKeyboardXmlId;
-            builder.load(keyboardXmlId, id);
-            if (mParams.mDisableTouchPositionCorrectionDataForTest) {
-                builder.disableTouchPositionCorrectionDataForTest();
-            }
-            builder.setProximityCharsCorrectionEnabled(
-                    elementParams.mProximityCharsCorrectionEnabled);
-            keyboard = builder.build();
-            sKeyboardCache.put(id, new SoftReference<Keyboard>(keyboard));
-            if ((id.mElementId == KeyboardId.ELEMENT_ALPHABET
-                    || id.mElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED)
-                    && !mParams.mIsSpellChecker) {
-                // We only forcibly cache the primary, "ALPHABET", layouts.
-                for (int i = sForcibleKeyboardCache.length - 1; i >= 1; --i) {
-                    sForcibleKeyboardCache[i] = sForcibleKeyboardCache[i - 1];
-                }
-                sForcibleKeyboardCache[0] = keyboard;
-                if (DEBUG_CACHE) {
-                    Log.d(TAG, "forcing caching of keyboard with id=" + id);
-                }
-            }
+        final Keyboard cachedKeyboard = (ref == null) ? null : ref.get();
+        if (cachedKeyboard != null) {
             if (DEBUG_CACHE) {
-                Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": "
-                        + ((ref == null) ? "LOAD" : "GCed") + " id=" + id);
+                Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": HIT  id=" + id);
             }
-        } else if (DEBUG_CACHE) {
-            Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": HIT  id=" + id);
+            return cachedKeyboard;
         }
 
+        final KeyboardBuilder<KeyboardParams> builder =
+                new KeyboardBuilder<KeyboardParams>(mContext, new KeyboardParams());
+        if (id.isAlphabetKeyboard()) {
+            builder.setAutoGenerate(sKeysCache);
+        }
+        final int keyboardXmlId = elementParams.mKeyboardXmlId;
+        builder.load(keyboardXmlId, id);
+        if (mParams.mDisableTouchPositionCorrectionDataForTest) {
+            builder.disableTouchPositionCorrectionDataForTest();
+        }
+        builder.setProximityCharsCorrectionEnabled(elementParams.mProximityCharsCorrectionEnabled);
+        final Keyboard keyboard = builder.build();
+        sKeyboardCache.put(id, new SoftReference<Keyboard>(keyboard));
+        if ((id.mElementId == KeyboardId.ELEMENT_ALPHABET
+                || id.mElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED)
+                && !mParams.mIsSpellChecker) {
+            // We only forcibly cache the primary, "ALPHABET", layouts.
+            for (int i = sForcibleKeyboardCache.length - 1; i >= 1; --i) {
+                sForcibleKeyboardCache[i] = sForcibleKeyboardCache[i - 1];
+            }
+            sForcibleKeyboardCache[0] = keyboard;
+            if (DEBUG_CACHE) {
+                Log.d(TAG, "forcing caching of keyboard with id=" + id);
+            }
+        }
+        if (DEBUG_CACHE) {
+            Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": "
+                    + ((ref == null) ? "LOAD" : "GCed") + " id=" + id);
+        }
         return keyboard;
     }
 
@@ -293,7 +294,7 @@
         }
 
         public Builder setIsSpellChecker(final boolean isSpellChecker) {
-            mParams.mIsSpellChecker = true;
+            mParams.mIsSpellChecker = isSpellChecker;
             return this;
         }
 
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
index d65aae2..69ffb4c 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
@@ -53,7 +53,6 @@
         "key_action_previous",
         "key_shift_enter",
         "key_language_switch",
-        "key_research",
         "key_unspecified",
         "key_left_parenthesis",
         "key_right_parenthesis",
@@ -90,7 +89,6 @@
         Constants.CODE_ACTION_PREVIOUS,
         Constants.CODE_SHIFT_ENTER,
         Constants.CODE_LANGUAGE_SWITCH,
-        Constants.CODE_RESEARCH,
         Constants.CODE_UNSPECIFIED,
         CODE_LEFT_PARENTHESIS,
         CODE_RIGHT_PARENTHESIS,
@@ -118,7 +116,6 @@
         DEFAULT[12],
         DEFAULT[13],
         DEFAULT[14],
-        DEFAULT[15],
         CODE_RIGHT_PARENTHESIS,
         CODE_LEFT_PARENTHESIS,
         CODE_GREATER_THAN_SIGN,
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
index 9848f3d..f91a21c 100644
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -187,7 +187,6 @@
     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;
     public static final int CODE_SHIFT_ENTER = -12;
     // Code value representing the code is not specified.
     public static final int CODE_UNSPECIFIED = -13;
@@ -212,7 +211,6 @@
         case CODE_UNSPECIFIED: return "unspec";
         case CODE_TAB: return "tab";
         case CODE_ENTER: return "enter";
-        case CODE_RESEARCH: return "research";
         default:
             if (code < CODE_SPACE) return String.format("'\\u%02x'", code);
             if (code < 0x100) return String.format("'%c'", code);
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index addf5c3..385e884 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1512,11 +1512,6 @@
         case Constants.CODE_LANGUAGE_SWITCH:
             handleLanguageSwitchKey();
             break;
-        case Constants.CODE_RESEARCH:
-            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                ResearchLogger.getInstance().onResearchKeySelected(this);
-            }
-            break;
         case Constants.CODE_ENTER:
             final EditorInfo editorInfo = getCurrentInputEditorInfo();
             final int imeOptionsActionId =
@@ -1608,6 +1603,11 @@
             resetComposingState(true /* alsoResetLastComposedWord */);
         }
         mHandler.postUpdateSuggestionStrip();
+        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS
+                && ResearchLogger.RESEARCH_KEY_OUTPUT_TEXT.equals(rawText)) {
+            ResearchLogger.getInstance().onResearchKeySelected(this);
+            return;
+        }
         final String text = specificTldProcessingOnTextInput(rawText);
         if (SPACE_STATE_PHANTOM == mSpaceState) {
             promotePhantomSpace();
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index 25187ced..0bd4939 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -132,6 +132,9 @@
     // FEEDBACK_WORD_BUFFER_SIZE should add 1 because it must also hold the feedback LogUnit itself.
     public static final int FEEDBACK_WORD_BUFFER_SIZE = (Integer.MAX_VALUE - 1) + 1;
 
+    // The special output text to invoke a research feedback dialog.
+    public static final String RESEARCH_KEY_OUTPUT_TEXT = ".research.";
+
     // constants related to specific log points
     private static final String WHITESPACE_SEPARATORS = " \t\n\r";
     private static final int MAX_INPUTVIEW_LENGTH_TO_CAPTURE = 8192; // must be >=1
@@ -402,6 +405,7 @@
     }
 
     public void onResearchKeySelected(final LatinIME latinIME) {
+        mCurrentLogUnit.removeResearchButtonInvocation();
         if (mInFeedbackDialog) {
             Toast.makeText(latinIME, R.string.research_please_exit_feedback_form,
                     Toast.LENGTH_LONG).show();
@@ -1506,16 +1510,9 @@
                     Constants.printableCode(scrubDigitFromCodePoint(code)),
                     outputText == null ? null : scrubDigitsFromString(outputText.toString()),
                     x, y, ignoreModifierKey, altersCode, key.isEnabled());
-            if (code == Constants.CODE_RESEARCH) {
-                researchLogger.suppressResearchKeyMotionData();
-            }
         }
     }
 
-    private void suppressResearchKeyMotionData() {
-        mCurrentLogUnit.removeResearchButtonInvocation();
-    }
-
     /**
      * Log a call to PointerTracker.callListenerCallListenerOnRelease().
      *