diff options
Diffstat (limited to 'java/src/com/android/inputmethod/research')
4 files changed, 77 insertions, 37 deletions
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) { |