aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java10
-rw-r--r--java/src/com/android/inputmethod/research/LogUnit.java8
-rw-r--r--java/src/com/android/inputmethod/research/MainLogBuffer.java4
-rw-r--r--java/src/com/android/inputmethod/research/ResearchLogger.java83
-rw-r--r--java/src/com/android/inputmethod/research/Statistics.java19
5 files changed, 83 insertions, 41 deletions
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 218ca2286..19076d2e7 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -820,10 +820,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
super.onFinishInput();
LatinImeLogger.commit();
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.getInstance().latinIME_onFinishInputInternal();
- }
-
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
if (mainKeyboardView != null) {
mainKeyboardView.closing();
@@ -840,6 +836,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// Remove pending messages related to update suggestions
mHandler.cancelUpdateSuggestionStrip();
resetComposingState(true /* alsoResetLastComposedWord */);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().latinIME_onFinishInputViewInternal();
+ }
}
@Override
@@ -1628,6 +1627,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
mConnection.setComposingText(batchInputText, 1);
mExpectingUpdateSelection = true;
mConnection.endBatchEdit();
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_onEndBatchInput(batchInputText, 0);
+ }
// Space state must be updated before calling updateShiftState
mSpaceState = SPACE_STATE_PHANTOM;
mKeyboardSwitcher.updateShiftState();
diff --git a/java/src/com/android/inputmethod/research/LogUnit.java b/java/src/com/android/inputmethod/research/LogUnit.java
index 3e542a43f..ab9d2f857 100644
--- a/java/src/com/android/inputmethod/research/LogUnit.java
+++ b/java/src/com/android/inputmethod/research/LogUnit.java
@@ -62,12 +62,16 @@ import java.util.List;
mIsPartOfMegaword = isPartOfMegaword;
}
+ private static final Object[] NULL_VALUES = new Object[0];
/**
* Adds a new log statement. The time parameter in successive calls to this method must be
* monotonically increasing, or splitByTime() will not work.
*/
- public void addLogStatement(final LogStatement logStatement, final Object[] values,
- final long time) {
+ public void addLogStatement(final LogStatement logStatement, final long time,
+ Object... values) {
+ if (values == null) {
+ values = NULL_VALUES;
+ }
mLogStatementList.add(logStatement);
mValuesList.add(values);
mTimeList.add(time);
diff --git a/java/src/com/android/inputmethod/research/MainLogBuffer.java b/java/src/com/android/inputmethod/research/MainLogBuffer.java
index 12c189f4a..b027643a1 100644
--- a/java/src/com/android/inputmethod/research/MainLogBuffer.java
+++ b/java/src/com/android/inputmethod/research/MainLogBuffer.java
@@ -119,6 +119,10 @@ public class MainLogBuffer extends LogBuffer {
} else {
// Words not in the dictionary are a privacy threat.
if (ResearchLogger.hasLetters(word) && !(dictionary.isValidWord(word))) {
+ if (DEBUG) {
+ Log.d(TAG, "NOT SAFE!: hasLetters: " + ResearchLogger.hasLetters(word)
+ + ", isValid: " + (dictionary.isValidWord(word)));
+ }
return false;
}
}
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index 9ea46eeb9..38c30017d 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -84,7 +84,7 @@ import java.util.UUID;
public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = ResearchLogger.class.getSimpleName();
private static final boolean DEBUG = false;
- private static final boolean OUTPUT_ENTIRE_BUFFER = false; // true may disclose private info
+ private static final boolean LOG_EVERYTHING = false; // true will disclose private info
public static final boolean DEFAULT_USABILITY_STUDY_MODE = false;
/* package */ static boolean sIsLogging = false;
private static final int OUTPUT_FORMAT_VERSION = 5;
@@ -136,7 +136,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
// used to check whether words are not unique
private Suggest mSuggest;
- private Dictionary mDictionary;
private MainKeyboardView mMainKeyboardView;
private InputMethodService mInputMethodService;
private final Statistics mStatistics;
@@ -379,7 +378,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
commitCurrentLogUnit();
if (mMainLogBuffer != null) {
- publishLogBuffer(mMainLogBuffer, mMainResearchLog, false /* isIncludingPrivateData */);
+ publishLogBuffer(mMainLogBuffer, mMainResearchLog,
+ LOG_EVERYTHING /* isIncludingPrivateData */);
mMainResearchLog.close(null /* callback */);
mMainLogBuffer = null;
}
@@ -565,10 +565,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
mFeedbackLogBuffer.clear();
}
final LogUnit feedbackLogUnit = new LogUnit();
- final Object[] values = {
- feedbackContents
- };
- feedbackLogUnit.addLogStatement(LOGSTATEMENT_FEEDBACK, values, SystemClock.uptimeMillis());
+ feedbackLogUnit.addLogStatement(LOGSTATEMENT_FEEDBACK, SystemClock.uptimeMillis(),
+ feedbackContents);
mFeedbackLogBuffer.shiftIn(feedbackLogUnit);
publishLogBuffer(mFeedbackLogBuffer, mFeedbackLog, true /* isIncludingPrivateData */);
mFeedbackLog.close(new Runnable() {
@@ -598,6 +596,13 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
}
+ private Dictionary getDictionary() {
+ if (mSuggest == null) {
+ return null;
+ }
+ return mSuggest.getMainDictionary();
+ }
+
private void setIsPasswordView(boolean isPasswordView) {
mIsPasswordView = isPasswordView;
}
@@ -653,19 +658,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
}
- private static final Object[] NULL_VALUES = {};
-
/**
* Buffer a research log event, flagging it as privacy-sensitive.
*/
private synchronized void enqueueEvent(LogStatement logStatement, Object... values) {
- if (values == null) {
- values = NULL_VALUES;
- }
assert values.length == logStatement.mKeys.length;
if (isAllowedToLog()) {
final long time = SystemClock.uptimeMillis();
- mCurrentLogUnit.addLogStatement(logStatement, values, time);
+ mCurrentLogUnit.addLogStatement(logStatement, time, values);
}
}
@@ -701,11 +701,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
/* package for test */ void publishLogBuffer(final LogBuffer logBuffer,
final ResearchLog researchLog, final boolean isIncludingPrivateData) {
final LogUnit openingLogUnit = new LogUnit();
- final Object[] values = {
- isIncludingPrivateData
- };
- openingLogUnit.addLogStatement(LOGSTATEMENT_LOG_SEGMENT_OPENING, values,
- SystemClock.uptimeMillis());
+ openingLogUnit.addLogStatement(LOGSTATEMENT_LOG_SEGMENT_OPENING, SystemClock.uptimeMillis(),
+ isIncludingPrivateData);
researchLog.publish(openingLogUnit, true /* isIncludingPrivateData */);
LogUnit logUnit;
while ((logUnit = logBuffer.shiftOut()) != null) {
@@ -716,7 +713,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
researchLog.publish(logUnit, isIncludingPrivateData);
}
final LogUnit closingLogUnit = new LogUnit();
- closingLogUnit.addLogStatement(LOGSTATEMENT_LOG_SEGMENT_CLOSING, NULL_VALUES,
+ closingLogUnit.addLogStatement(LOGSTATEMENT_LOG_SEGMENT_CLOSING,
SystemClock.uptimeMillis());
researchLog.publish(closingLogUnit, true /* isIncludingPrivateData */);
}
@@ -732,19 +729,22 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
return false;
}
- private static final LogStatement LOGSTATEMENT_COMMIT_AUTOSPACE =
- new LogStatement("CommitAutospace", true, false);
- private void onWordComplete(final String word, final long maxTime, final boolean isPartial) {
- Log.d(TAG, "onWordComplete: " + word);
+ private static final LogStatement LOGSTATEMENT_COMMIT_RECORD_SPLIT_WORDS =
+ new LogStatement("recordSplitWords", true, false);
+ private void onWordComplete(final String word, final long maxTime, final boolean isSplitWords) {
+ final Dictionary dictionary = getDictionary();
if (word != null && word.length() > 0 && hasLetters(word)) {
mCurrentLogUnit.setWord(word);
- mStatistics.recordWordEntered();
+ final boolean isDictionaryWord = dictionary != null
+ && dictionary.isValidWord(word);
+ mStatistics.recordWordEntered(isDictionaryWord);
}
final LogUnit newLogUnit = mCurrentLogUnit.splitByTime(maxTime);
enqueueCommitText(word);
- if (isPartial) {
- enqueueEvent(LOGSTATEMENT_COMMIT_AUTOSPACE, NULL_VALUES);
+ if (isSplitWords) {
+ enqueueEvent(LOGSTATEMENT_COMMIT_RECORD_SPLIT_WORDS);
enqueueCommitText(" ");
+ mStatistics.recordSplitWords();
}
commitCurrentLogUnit();
mCurrentLogUnit = newLogUnit;
@@ -791,10 +791,11 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
private String scrubWord(String word) {
- if (mDictionary == null) {
+ final Dictionary dictionary = getDictionary();
+ if (dictionary == null) {
return WORD_REPLACEMENT_STRING;
}
- if (mDictionary.isValidWord(word)) {
+ if (dictionary.isValidWord(word)) {
return word;
}
return WORD_REPLACEMENT_STRING;
@@ -803,7 +804,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
private static final LogStatement LOGSTATEMENT_LATIN_IME_ON_START_INPUT_VIEW_INTERNAL =
new LogStatement("LatinImeOnStartInputViewInternal", false, false, "uuid",
"packageName", "inputType", "imeOptions", "fieldId", "display", "model",
- "prefs", "versionCode", "versionName", "outputFormatVersion");
+ "prefs", "versionCode", "versionName", "outputFormatVersion", "logEverything");
public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo,
final SharedPreferences prefs) {
final ResearchLogger researchLogger = getInstance();
@@ -824,14 +825,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
Integer.toHexString(editorInfo.inputType),
Integer.toHexString(editorInfo.imeOptions), editorInfo.fieldId,
Build.DISPLAY, Build.MODEL, prefs, versionCode, versionName,
- OUTPUT_FORMAT_VERSION);
+ OUTPUT_FORMAT_VERSION, LOG_EVERYTHING);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
}
}
- public void latinIME_onFinishInputInternal() {
+ public void latinIME_onFinishInputViewInternal() {
stop();
}
@@ -904,7 +905,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
if (ic != null) {
final boolean isTextTruncated;
final String text;
- if (OUTPUT_ENTIRE_BUFFER) {
+ if (LOG_EVERYTHING) {
// Capture the TextView contents. This will trigger onUpdateSelection(), so we
// set sLatinIMEExpectingUpdateSelection so that when onUpdateSelection() is called,
// it can tell that it was generated by the logging code, and not by the user, and
@@ -1205,11 +1206,23 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
getInstance().enqueueEvent(LOGSTATEMENT_USER_TIMESTAMP);
}
+ private static final LogStatement LOGSTATEMENT_LATINIME_ONENDBATCHINPUT =
+ new LogStatement("LatinIMEOnEndBatchInput", true, false, "enteredText",
+ "enteredWordPos");
+ public static void latinIME_onEndBatchInput(final CharSequence enteredText,
+ final int enteredWordPos) {
+ final ResearchLogger researchLogger = getInstance();
+ researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_ONENDBATCHINPUT, enteredText,
+ enteredWordPos);
+ researchLogger.mStatistics.recordGestureInput();
+ }
+
private static final LogStatement LOGSTATEMENT_STATISTICS =
new LogStatement("Statistics", false, false, "charCount", "letterCount", "numberCount",
"spaceCount", "deleteOpsCount", "wordCount", "isEmptyUponStarting",
"isEmptinessStateKnown", "averageTimeBetweenKeys", "averageTimeBeforeDelete",
- "averageTimeDuringRepeatedDelete", "averageTimeAfterDelete");
+ "averageTimeDuringRepeatedDelete", "averageTimeAfterDelete",
+ "dictionaryWordCount", "splitWordsCount", "gestureInputCount");
private static void logStatistics() {
final ResearchLogger researchLogger = getInstance();
final Statistics statistics = researchLogger.mStatistics;
@@ -1219,6 +1232,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
statistics.mIsEmptinessStateKnown, statistics.mKeyCounter.getAverageTime(),
statistics.mBeforeDeleteKeyCounter.getAverageTime(),
statistics.mDuringRepeatedDeleteKeysCounter.getAverageTime(),
- statistics.mAfterDeleteKeyCounter.getAverageTime());
+ statistics.mAfterDeleteKeyCounter.getAverageTime(),
+ statistics.mDictionaryWordCount, statistics.mSplitWordsCount,
+ statistics.mGestureInputCount);
}
}
diff --git a/java/src/com/android/inputmethod/research/Statistics.java b/java/src/com/android/inputmethod/research/Statistics.java
index 2065ab15e..90d7f38b3 100644
--- a/java/src/com/android/inputmethod/research/Statistics.java
+++ b/java/src/com/android/inputmethod/research/Statistics.java
@@ -36,6 +36,12 @@ public class Statistics {
int mDeleteKeyCount;
// Number of words entered during a session.
int mWordCount;
+ // Number of words found in the dictionary.
+ int mDictionaryWordCount;
+ // Number of words split and spaces automatically entered.
+ int mSplitWordsCount;
+ // Number of gestures that were input.
+ int mGestureInputCount;
// Whether the text field was empty upon editing
boolean mIsEmptyUponStarting;
boolean mIsEmptinessStateKnown;
@@ -143,8 +149,19 @@ public class Statistics {
mLastTapTime = time;
}
- public void recordWordEntered() {
+ public void recordWordEntered(final boolean isDictionaryWord) {
mWordCount++;
+ if (isDictionaryWord) {
+ mDictionaryWordCount++;
+ }
+ }
+
+ public void recordSplitWords() {
+ mSplitWordsCount++;
+ }
+
+ public void recordGestureInput() {
+ mGestureInputCount++;
}
public void setIsEmptyUponStarting(final boolean isEmpty) {