[Rlog32] ResearchLogger segment motion data around gestures correctly

multi-project commit with I684ba5fed8c653777942e6b0366113ca40dfa37c

Change-Id: Id3804e6cfa97b4cdde212b8eebc413f76fa4772c
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index e72aa55..49d8813 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1153,7 +1153,7 @@
             commitChosenWord(typedWord, LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD,
                     separatorString);
             if (ProductionFlag.IS_EXPERIMENTAL) {
-                ResearchLogger.getInstance().onWordComplete(typedWord, Long.MAX_VALUE);
+                ResearchLogger.getInstance().onWordFinished(typedWord);
             }
         }
     }
@@ -1193,8 +1193,7 @@
             final String text = lastTwo.charAt(1) + " ";
             mConnection.commitText(text, 1);
             if (ProductionFlag.IS_EXPERIMENTAL) {
-                ResearchLogger.getInstance().onWordComplete(text, Long.MAX_VALUE);
-                ResearchLogger.latinIME_swapSwapperAndSpace();
+                ResearchLogger.latinIME_swapSwapperAndSpace(text);
             }
             mKeyboardSwitcher.updateShiftState();
         }
@@ -1214,7 +1213,7 @@
             final String textToInsert = ". ";
             mConnection.commitText(textToInsert, 1);
             if (ProductionFlag.IS_EXPERIMENTAL) {
-                ResearchLogger.getInstance().onWordComplete(textToInsert, Long.MAX_VALUE);
+                ResearchLogger.latinIME_maybeDoubleSpacePeriod(textToInsert);
             }
             mKeyboardSwitcher.updateShiftState();
             return true;
@@ -1465,7 +1464,7 @@
         }
         mConnection.commitText(text, 1);
         if (ProductionFlag.IS_EXPERIMENTAL) {
-            ResearchLogger.getInstance().onWordComplete(text, Long.MAX_VALUE);
+            ResearchLogger.latinIME_onTextInput(text);
         }
         mConnection.endBatchEdit();
         // Space state must be updated before calling updateShiftState
@@ -1726,7 +1725,7 @@
             }
             if (SPACE_STATE_DOUBLE == spaceState) {
                 mHandler.cancelDoubleSpacePeriodTimer();
-                if (mConnection.revertDoubleSpace()) {
+                if (mConnection.revertDoubleSpacePeriod()) {
                     // No need to reset mSpaceState, it has already be done (that's why we
                     // receive it as a parameter)
                     return;
@@ -2324,7 +2323,6 @@
         }
         if (ProductionFlag.IS_EXPERIMENTAL) {
             ResearchLogger.latinIME_revertCommit(committedWord, originallyTypedWord);
-            ResearchLogger.getInstance().onWordComplete(originallyTypedWord, Long.MAX_VALUE);
         }
         // Don't restart suggestion yet. We'll restart if the user deletes the
         // separator.
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index fe4a257..380e888 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -648,7 +648,7 @@
         return word;
     }
 
-    public boolean revertDoubleSpace() {
+    public boolean revertDoubleSpacePeriod() {
         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.
@@ -665,7 +665,7 @@
         final String doubleSpace = "  ";
         commitText(doubleSpace, 1);
         if (ProductionFlag.IS_EXPERIMENTAL) {
-            ResearchLogger.getInstance().onWordComplete(doubleSpace, Long.MAX_VALUE);
+            ResearchLogger.richInputConnection_revertDoubleSpacePeriod(doubleSpace);
         }
         return true;
     }
@@ -690,7 +690,7 @@
         final String text = " " + textBeforeCursor.subSequence(0, 1);
         commitText(text, 1);
         if (ProductionFlag.IS_EXPERIMENTAL) {
-            ResearchLogger.getInstance().onWordComplete(text, Long.MAX_VALUE);
+            ResearchLogger.richInputConnection_revertSwapPunctuation(text);
         }
         return true;
     }
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index cde100a..dfb640b 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -153,6 +153,11 @@
 
     private LogUnit mCurrentLogUnit = new LogUnit();
 
+    // Gestured or tapped words may be committed after the gesture of the next word has started.
+    // To ensure that the gesture data of the next word is not associated with the previous word,
+    // thereby leaking private data, we store the time of the down event that started the second
+    // gesture, and when committing the earlier word, split the LogUnit.
+    private long mSavedDownEventTime;
     private ResearchLogger() {
         mStatistics = Statistics.getInstance();
     }
@@ -739,9 +744,15 @@
         return false;
     }
 
+    /**
+     * Commit the portion of mCurrentLogUnit before maxTime as a worded logUnit.
+     *
+     * After this operation completes, mCurrentLogUnit will hold any logStatements that happened
+     * after maxTime.
+     */
     private static final LogStatement LOGSTATEMENT_COMMIT_RECORD_SPLIT_WORDS =
             new LogStatement("recordSplitWords", true, false);
-    public void onWordComplete(final String word, final long maxTime) {
+    /* package for test */ void commitCurrentLogUnitAsWord(final String word, final long maxTime) {
         final Dictionary dictionary = getDictionary();
         if (word != null && word.length() > 0 && hasLetters(word)) {
             mCurrentLogUnit.setWord(word);
@@ -755,6 +766,11 @@
         mCurrentLogUnit = newLogUnit;
     }
 
+    public void onWordFinished(final String word) {
+        commitCurrentLogUnitAsWord(word, mSavedDownEventTime);
+        mSavedDownEventTime = Long.MAX_VALUE;
+    }
+
     private static int scrubDigitFromCodePoint(int codePoint) {
         return Character.isDigit(codePoint) ? DIGIT_REPLACEMENT_CODEPOINT : codePoint;
     }
@@ -896,8 +912,14 @@
             }
             final float size = me.getSize(index);
             final float pressure = me.getPressure(index);
-            getInstance().enqueueEvent(LOGSTATEMENT_MAIN_KEYBOARD_VIEW_PROCESS_MOTION_EVENT,
+            final ResearchLogger researchLogger = getInstance();
+            researchLogger.enqueueEvent(LOGSTATEMENT_MAIN_KEYBOARD_VIEW_PROCESS_MOTION_EVENT,
                     actionString, eventTime, id, x, y, size, pressure);
+            if (action == MotionEvent.ACTION_DOWN) {
+                // Subtract 1 from eventTime so the down event is included in the later
+                // LogUnit, not the earlier (the test is for inequality).
+                researchLogger.mSavedDownEventTime = eventTime - 1;
+            }
         }
     }
 
@@ -1036,6 +1058,16 @@
     }
 
     /**
+     * Log a call to LatinIME.onTextInput().
+     *
+     * SystemResponse: Raw text is added to the TextView.
+     */
+    public static void latinIME_onTextInput(final String text) {
+        final ResearchLogger researchLogger = getInstance();
+        researchLogger.commitCurrentLogUnitAsWord(text, Long.MAX_VALUE);
+    }
+
+    /**
      * Log a call to LatinIME.pickSuggestionManually().
      *
      * UserAction: The user has chosen a specific word from the suggestion strip.
@@ -1051,7 +1083,7 @@
                 scrubDigitsFromString(replacedWord), index,
                 suggestion == null ? null : scrubbedWord, Constants.SUGGESTION_STRIP_COORDINATE,
                 Constants.SUGGESTION_STRIP_COORDINATE);
-        researchLogger.onWordComplete(scrubbedWord, Long.MAX_VALUE);
+        researchLogger.commitCurrentLogUnitAsWord(scrubbedWord, Long.MAX_VALUE);
         researchLogger.mStatistics.recordManualSuggestion();
     }
 
@@ -1067,7 +1099,7 @@
         final ResearchLogger researchLogger = getInstance();
         researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_PUNCTUATIONSUGGESTION, index, suggestion,
                 Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE);
-        researchLogger.onWordComplete(suggestion, Long.MAX_VALUE);
+        researchLogger.commitCurrentLogUnitAsWord(suggestion, Long.MAX_VALUE);
     }
 
     /**
@@ -1096,8 +1128,20 @@
      */
     private static final LogStatement LOGSTATEMENT_LATINIME_SWAPSWAPPERANDSPACE =
             new LogStatement("LatinIMESwapSwapperAndSpace", false, false);
-    public static void latinIME_swapSwapperAndSpace() {
-        getInstance().enqueueEvent(LOGSTATEMENT_LATINIME_SWAPSWAPPERANDSPACE);
+    public static void latinIME_swapSwapperAndSpace(final String text) {
+        final ResearchLogger researchLogger = getInstance();
+        researchLogger.commitCurrentLogUnitAsWord(text, Long.MAX_VALUE);
+        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_SWAPSWAPPERANDSPACE);
+    }
+
+    /**
+     * Log a call to LatinIME.maybeDoubleSpacePeriod().
+     *
+     * SystemResponse: Two spaces have been replaced by period space.
+     */
+    public static void latinIME_maybeDoubleSpacePeriod(final String text) {
+        final ResearchLogger researchLogger = getInstance();
+        researchLogger.commitCurrentLogUnitAsWord(text, Long.MAX_VALUE);
     }
 
     /**
@@ -1154,6 +1198,7 @@
         researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_REVERTCOMMIT, committedWord,
                 originallyTypedWord);
         researchLogger.mStatistics.recordRevertCommit();
+        researchLogger.commitCurrentLogUnitAsWord(originallyTypedWord, Long.MAX_VALUE);
     }
 
     /**
@@ -1248,6 +1293,26 @@
     }
 
     /**
+     * Log a call to RichInputConnection.revertDoubleSpacePeriod().
+     *
+     * SystemResponse: The IME has reverted ". ", which had previously replaced two typed spaces.
+     */
+    public static void richInputConnection_revertDoubleSpacePeriod(final String doubleSpace) {
+        final ResearchLogger researchLogger = getInstance();
+        researchLogger.commitCurrentLogUnitAsWord(doubleSpace, Long.MAX_VALUE);
+    }
+
+    /**
+     * Log a call to RichInputConnection.revertSwapPunctuation().
+     *
+     * SystemResponse: The IME has reverted a punctuation swap.
+     */
+    public static void richInputConnection_revertSwapPunctuation(final String text) {
+        final ResearchLogger researchLogger = getInstance();
+        researchLogger.commitCurrentLogUnitAsWord(text, Long.MAX_VALUE);
+    }
+
+    /**
      * Log a call to LatinIME.commitCurrentAutoCorrection().
      *
      * SystemResponse: The IME has committed an auto-correction.  An auto-correction changes the raw
@@ -1263,7 +1328,7 @@
         final ResearchLogger researchLogger = getInstance();
         researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_COMMITCURRENTAUTOCORRECTION,
                 scrubbedTypedWord, scrubbedAutoCorrection, separatorString);
-        researchLogger.onWordComplete(scrubbedAutoCorrection, Long.MAX_VALUE);
+        researchLogger.commitCurrentLogUnitAsWord(scrubbedAutoCorrection, Long.MAX_VALUE);
     }
 
     private boolean isExpectingCommitText = false;
@@ -1282,7 +1347,7 @@
         final ResearchLogger researchLogger = getInstance();
         final String scrubbedWord = scrubDigitsFromString(committedWord.toString());
         researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_COMMIT_PARTIAL_TEXT);
-        researchLogger.onWordComplete(scrubbedWord, lastTimestampOfWordData);
+        researchLogger.commitCurrentLogUnitAsWord(scrubbedWord, lastTimestampOfWordData);
         researchLogger.mStatistics.recordSplitWords();
     }
 
@@ -1301,7 +1366,7 @@
         if (!researchLogger.isExpectingCommitText) {
             researchLogger.enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTIONCOMMITTEXT,
                     newCursorPosition);
-            researchLogger.onWordComplete(scrubbedWord, Long.MAX_VALUE);
+            researchLogger.commitCurrentLogUnitAsWord(scrubbedWord, Long.MAX_VALUE);
         }
         researchLogger.isExpectingCommitText = false;
     }