Loading java/src/com/android/inputmethod/research/LogStatement.java +77 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,18 @@ package com.android.inputmethod.research; import android.content.SharedPreferences; import android.util.JsonWriter; import android.util.Log; import android.view.MotionEvent; import android.view.inputmethod.CompletionInfo; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.define.ProductionFlag; import java.io.IOException; /** * A template for typed information stored in the logs. * Loading @@ -24,6 +36,9 @@ package com.android.inputmethod.research; * actual values are stored separately. */ class LogStatement { private static final String TAG = LogStatement.class.getSimpleName(); private static final boolean DEBUG = false && ProductionFlag.IS_EXPERIMENTAL_DEBUG; // Constants for particular statements public static final String TYPE_POINTER_TRACKER_CALL_LISTENER_ON_CODE_INPUT = "PointerTrackerCallListenerOnCodeInput"; Loading @@ -36,6 +51,11 @@ class LogStatement { public static final String TYPE_MOTION_EVENT = "MotionEvent"; public static final String KEY_IS_LOGGING_RELATED = "isLoggingRelated"; // Keys for internal key/value pairs private static final String CURRENT_TIME_KEY = "_ct"; private static final String UPTIME_KEY = "_ut"; private static final String EVENT_TYPE_KEY = "_ty"; // Name specifying the LogStatement type. private final String mType; Loading Loading @@ -142,4 +162,61 @@ class LogStatement { } return false; } /** * Write the contents out through jsonWriter. * * Note that this method is not thread safe for the same jsonWriter. Callers must ensure * thread safety. */ public boolean outputToLocked(final JsonWriter jsonWriter, final Long time, final Object... values) { if (DEBUG) { if (mKeys.length != values.length) { Log.d(TAG, "Key and Value list sizes do not match. " + mType); } } try { jsonWriter.beginObject(); jsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis()); jsonWriter.name(UPTIME_KEY).value(time); jsonWriter.name(EVENT_TYPE_KEY).value(mType); final int length = values.length; for (int i = 0; i < length; i++) { jsonWriter.name(mKeys[i]); final Object value = values[i]; if (value instanceof CharSequence) { jsonWriter.value(value.toString()); } else if (value instanceof Number) { jsonWriter.value((Number) value); } else if (value instanceof Boolean) { jsonWriter.value((Boolean) value); } else if (value instanceof CompletionInfo[]) { JsonUtils.writeJson((CompletionInfo[]) value, jsonWriter); } else if (value instanceof SharedPreferences) { JsonUtils.writeJson((SharedPreferences) value, jsonWriter); } else if (value instanceof Key[]) { JsonUtils.writeJson((Key[]) value, jsonWriter); } else if (value instanceof SuggestedWords) { JsonUtils.writeJson((SuggestedWords) value, jsonWriter); } else if (value instanceof MotionEvent) { JsonUtils.writeJson((MotionEvent) value, jsonWriter); } else if (value == null) { jsonWriter.nullValue(); } else { if (DEBUG) { Log.w(TAG, "Unrecognized type to be logged: " + (value == null ? "<null>" : value.getClass().getName())); } jsonWriter.nullValue(); } } jsonWriter.endObject(); } catch (IOException e) { e.printStackTrace(); Log.w(TAG, "Error in JsonWriter; skipping LogStatement"); return false; } return true; } } java/src/com/android/inputmethod/research/LogUnit.java +21 −87 Original line number Diff line number Diff line Loading @@ -17,13 +17,11 @@ package com.android.inputmethod.research; import android.content.SharedPreferences; import android.os.SystemClock; import android.text.TextUtils; import android.util.JsonWriter; import android.util.Log; import android.view.MotionEvent; import android.view.inputmethod.CompletionInfo; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.define.ProductionFlag; Loading Loading @@ -153,11 +151,10 @@ import java.util.List; jsonWriter = researchLog.getValidJsonWriterLocked(); outputLogUnitStart(jsonWriter, canIncludePrivateData); } outputLogStatementToLocked(jsonWriter, mLogStatementList.get(i), mValuesList.get(i), mTimeList.get(i)); logStatement.outputToLocked(jsonWriter, mTimeList.get(i), mValuesList.get(i)); if (DEBUG) { outputLogStatementToLocked(debugJsonWriter, mLogStatementList.get(i), mValuesList.get(i), mTimeList.get(i)); logStatement.outputToLocked(debugJsonWriter, mTimeList.get(i), mValuesList.get(i)); } } if (jsonWriter != null) { Loading @@ -180,97 +177,34 @@ import java.util.List; } } private static final String CURRENT_TIME_KEY = "_ct"; private static final String UPTIME_KEY = "_ut"; private static final String EVENT_TYPE_KEY = "_ty"; private static final String WORD_KEY = "_wo"; private static final String CORRECTION_TYPE_KEY = "_corType"; private static final String LOG_UNIT_BEGIN_KEY = "logUnitStart"; private static final String LOG_UNIT_END_KEY = "logUnitEnd"; final LogStatement LOGSTATEMENT_LOG_UNIT_BEGIN_WITH_PRIVATE_DATA = new LogStatement(LOG_UNIT_BEGIN_KEY, false /* isPotentiallyPrivate */, false /* isPotentiallyRevealing */, WORD_KEY, CORRECTION_TYPE_KEY); final LogStatement LOGSTATEMENT_LOG_UNIT_BEGIN_WITHOUT_PRIVATE_DATA = new LogStatement(LOG_UNIT_BEGIN_KEY, false /* isPotentiallyPrivate */, false /* isPotentiallyRevealing */); private void outputLogUnitStart(final JsonWriter jsonWriter, final boolean canIncludePrivateData) { try { jsonWriter.beginObject(); jsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis()); final LogStatement logStatement; if (canIncludePrivateData) { jsonWriter.name(WORD_KEY).value(getWord()); jsonWriter.name(CORRECTION_TYPE_KEY).value(getCorrectionType()); } jsonWriter.name(EVENT_TYPE_KEY).value(LOG_UNIT_BEGIN_KEY); jsonWriter.endObject(); } catch (IOException e) { e.printStackTrace(); Log.w(TAG, "Error in JsonWriter; cannot write LogUnitStart"); LOGSTATEMENT_LOG_UNIT_BEGIN_WITH_PRIVATE_DATA.outputToLocked(jsonWriter, SystemClock.uptimeMillis(), getWord(), getCorrectionType()); } else { LOGSTATEMENT_LOG_UNIT_BEGIN_WITHOUT_PRIVATE_DATA.outputToLocked(jsonWriter, SystemClock.uptimeMillis()); } } final LogStatement LOGSTATEMENT_LOG_UNIT_END = new LogStatement(LOG_UNIT_END_KEY, false /* isPotentiallyPrivate */, false /* isPotentiallyRevealing */); private void outputLogUnitStop(final JsonWriter jsonWriter) { try { jsonWriter.beginObject(); jsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis()); jsonWriter.name(EVENT_TYPE_KEY).value(LOG_UNIT_END_KEY); jsonWriter.endObject(); } catch (IOException e) { e.printStackTrace(); Log.w(TAG, "Error in JsonWriter; cannot write LogUnitStop"); } } /** * Write the logStatement and its contents out through jsonWriter. * * Note that this method is not thread safe for the same jsonWriter. Callers must ensure * thread safety. */ private boolean outputLogStatementToLocked(final JsonWriter jsonWriter, final LogStatement logStatement, final Object[] values, final Long time) { if (DEBUG) { if (logStatement.getKeys().length != values.length) { Log.d(TAG, "Key and Value list sizes do not match. " + logStatement.getType()); } } try { jsonWriter.beginObject(); jsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis()); jsonWriter.name(UPTIME_KEY).value(time); jsonWriter.name(EVENT_TYPE_KEY).value(logStatement.getType()); final String[] keys = logStatement.getKeys(); final int length = values.length; for (int i = 0; i < length; i++) { jsonWriter.name(keys[i]); final Object value = values[i]; if (value instanceof CharSequence) { jsonWriter.value(value.toString()); } else if (value instanceof Number) { jsonWriter.value((Number) value); } else if (value instanceof Boolean) { jsonWriter.value((Boolean) value); } else if (value instanceof CompletionInfo[]) { JsonUtils.writeJson((CompletionInfo[]) value, jsonWriter); } else if (value instanceof SharedPreferences) { JsonUtils.writeJson((SharedPreferences) value, jsonWriter); } else if (value instanceof Key[]) { JsonUtils.writeJson((Key[]) value, jsonWriter); } else if (value instanceof SuggestedWords) { JsonUtils.writeJson((SuggestedWords) value, jsonWriter); } else if (value instanceof MotionEvent) { JsonUtils.writeJson((MotionEvent) value, jsonWriter); } else if (value == null) { jsonWriter.nullValue(); } else { Log.w(TAG, "Unrecognized type to be logged: " + (value == null ? "<null>" : value.getClass().getName())); jsonWriter.nullValue(); } } jsonWriter.endObject(); } catch (IOException e) { e.printStackTrace(); Log.w(TAG, "Error in JsonWriter; skipping LogStatement"); return false; } return true; LOGSTATEMENT_LOG_UNIT_END.outputToLocked(jsonWriter, SystemClock.uptimeMillis()); } /** Loading java/src/com/android/inputmethod/research/ResearchLogger.java +11 −3 Original line number Diff line number Diff line Loading @@ -1003,15 +1003,23 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } /** * Publish all the logUnits in the logBuffer, without doing any privacy filtering. */ /* package for test */ void publishLogBuffer(final LogBuffer logBuffer, final ResearchLog researchLog, final boolean isIncludingPrivateData) { publishLogUnits(logBuffer.getLogUnits(), researchLog, isIncludingPrivateData); final ResearchLog researchLog, final boolean canIncludePrivateData) { publishLogUnits(logBuffer.getLogUnits(), researchLog, canIncludePrivateData); } private static final LogStatement LOGSTATEMENT_LOG_SEGMENT_OPENING = new LogStatement("logSegmentStart", false, false, "isIncludingPrivateData"); private static final LogStatement LOGSTATEMENT_LOG_SEGMENT_CLOSING = new LogStatement("logSegmentEnd", false, false); /** * Publish all LogUnits in a list. * * Any privacy checks should be performed before calling this method. */ /* package for test */ void publishLogUnits(final List<LogUnit> logUnits, final ResearchLog researchLog, final boolean canIncludePrivateData) { final LogUnit openingLogUnit = new LogUnit(); Loading Loading @@ -1392,7 +1400,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final int index, final String suggestion, final boolean isBatchMode) { final ResearchLogger researchLogger = getInstance(); if (!replacedWord.equals(suggestion.toString())) { // The user choose something other than what was already there. // The user chose something other than what was already there. researchLogger.setCurrentLogUnitContainsCorrection(); researchLogger.setCurrentLogUnitCorrectionType(LogUnit.CORRECTIONTYPE_TYPO); } Loading Loading
java/src/com/android/inputmethod/research/LogStatement.java +77 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,18 @@ package com.android.inputmethod.research; import android.content.SharedPreferences; import android.util.JsonWriter; import android.util.Log; import android.view.MotionEvent; import android.view.inputmethod.CompletionInfo; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.define.ProductionFlag; import java.io.IOException; /** * A template for typed information stored in the logs. * Loading @@ -24,6 +36,9 @@ package com.android.inputmethod.research; * actual values are stored separately. */ class LogStatement { private static final String TAG = LogStatement.class.getSimpleName(); private static final boolean DEBUG = false && ProductionFlag.IS_EXPERIMENTAL_DEBUG; // Constants for particular statements public static final String TYPE_POINTER_TRACKER_CALL_LISTENER_ON_CODE_INPUT = "PointerTrackerCallListenerOnCodeInput"; Loading @@ -36,6 +51,11 @@ class LogStatement { public static final String TYPE_MOTION_EVENT = "MotionEvent"; public static final String KEY_IS_LOGGING_RELATED = "isLoggingRelated"; // Keys for internal key/value pairs private static final String CURRENT_TIME_KEY = "_ct"; private static final String UPTIME_KEY = "_ut"; private static final String EVENT_TYPE_KEY = "_ty"; // Name specifying the LogStatement type. private final String mType; Loading Loading @@ -142,4 +162,61 @@ class LogStatement { } return false; } /** * Write the contents out through jsonWriter. * * Note that this method is not thread safe for the same jsonWriter. Callers must ensure * thread safety. */ public boolean outputToLocked(final JsonWriter jsonWriter, final Long time, final Object... values) { if (DEBUG) { if (mKeys.length != values.length) { Log.d(TAG, "Key and Value list sizes do not match. " + mType); } } try { jsonWriter.beginObject(); jsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis()); jsonWriter.name(UPTIME_KEY).value(time); jsonWriter.name(EVENT_TYPE_KEY).value(mType); final int length = values.length; for (int i = 0; i < length; i++) { jsonWriter.name(mKeys[i]); final Object value = values[i]; if (value instanceof CharSequence) { jsonWriter.value(value.toString()); } else if (value instanceof Number) { jsonWriter.value((Number) value); } else if (value instanceof Boolean) { jsonWriter.value((Boolean) value); } else if (value instanceof CompletionInfo[]) { JsonUtils.writeJson((CompletionInfo[]) value, jsonWriter); } else if (value instanceof SharedPreferences) { JsonUtils.writeJson((SharedPreferences) value, jsonWriter); } else if (value instanceof Key[]) { JsonUtils.writeJson((Key[]) value, jsonWriter); } else if (value instanceof SuggestedWords) { JsonUtils.writeJson((SuggestedWords) value, jsonWriter); } else if (value instanceof MotionEvent) { JsonUtils.writeJson((MotionEvent) value, jsonWriter); } else if (value == null) { jsonWriter.nullValue(); } else { if (DEBUG) { Log.w(TAG, "Unrecognized type to be logged: " + (value == null ? "<null>" : value.getClass().getName())); } jsonWriter.nullValue(); } } jsonWriter.endObject(); } catch (IOException e) { e.printStackTrace(); Log.w(TAG, "Error in JsonWriter; skipping LogStatement"); return false; } return true; } }
java/src/com/android/inputmethod/research/LogUnit.java +21 −87 Original line number Diff line number Diff line Loading @@ -17,13 +17,11 @@ package com.android.inputmethod.research; import android.content.SharedPreferences; import android.os.SystemClock; import android.text.TextUtils; import android.util.JsonWriter; import android.util.Log; import android.view.MotionEvent; import android.view.inputmethod.CompletionInfo; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.define.ProductionFlag; Loading Loading @@ -153,11 +151,10 @@ import java.util.List; jsonWriter = researchLog.getValidJsonWriterLocked(); outputLogUnitStart(jsonWriter, canIncludePrivateData); } outputLogStatementToLocked(jsonWriter, mLogStatementList.get(i), mValuesList.get(i), mTimeList.get(i)); logStatement.outputToLocked(jsonWriter, mTimeList.get(i), mValuesList.get(i)); if (DEBUG) { outputLogStatementToLocked(debugJsonWriter, mLogStatementList.get(i), mValuesList.get(i), mTimeList.get(i)); logStatement.outputToLocked(debugJsonWriter, mTimeList.get(i), mValuesList.get(i)); } } if (jsonWriter != null) { Loading @@ -180,97 +177,34 @@ import java.util.List; } } private static final String CURRENT_TIME_KEY = "_ct"; private static final String UPTIME_KEY = "_ut"; private static final String EVENT_TYPE_KEY = "_ty"; private static final String WORD_KEY = "_wo"; private static final String CORRECTION_TYPE_KEY = "_corType"; private static final String LOG_UNIT_BEGIN_KEY = "logUnitStart"; private static final String LOG_UNIT_END_KEY = "logUnitEnd"; final LogStatement LOGSTATEMENT_LOG_UNIT_BEGIN_WITH_PRIVATE_DATA = new LogStatement(LOG_UNIT_BEGIN_KEY, false /* isPotentiallyPrivate */, false /* isPotentiallyRevealing */, WORD_KEY, CORRECTION_TYPE_KEY); final LogStatement LOGSTATEMENT_LOG_UNIT_BEGIN_WITHOUT_PRIVATE_DATA = new LogStatement(LOG_UNIT_BEGIN_KEY, false /* isPotentiallyPrivate */, false /* isPotentiallyRevealing */); private void outputLogUnitStart(final JsonWriter jsonWriter, final boolean canIncludePrivateData) { try { jsonWriter.beginObject(); jsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis()); final LogStatement logStatement; if (canIncludePrivateData) { jsonWriter.name(WORD_KEY).value(getWord()); jsonWriter.name(CORRECTION_TYPE_KEY).value(getCorrectionType()); } jsonWriter.name(EVENT_TYPE_KEY).value(LOG_UNIT_BEGIN_KEY); jsonWriter.endObject(); } catch (IOException e) { e.printStackTrace(); Log.w(TAG, "Error in JsonWriter; cannot write LogUnitStart"); LOGSTATEMENT_LOG_UNIT_BEGIN_WITH_PRIVATE_DATA.outputToLocked(jsonWriter, SystemClock.uptimeMillis(), getWord(), getCorrectionType()); } else { LOGSTATEMENT_LOG_UNIT_BEGIN_WITHOUT_PRIVATE_DATA.outputToLocked(jsonWriter, SystemClock.uptimeMillis()); } } final LogStatement LOGSTATEMENT_LOG_UNIT_END = new LogStatement(LOG_UNIT_END_KEY, false /* isPotentiallyPrivate */, false /* isPotentiallyRevealing */); private void outputLogUnitStop(final JsonWriter jsonWriter) { try { jsonWriter.beginObject(); jsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis()); jsonWriter.name(EVENT_TYPE_KEY).value(LOG_UNIT_END_KEY); jsonWriter.endObject(); } catch (IOException e) { e.printStackTrace(); Log.w(TAG, "Error in JsonWriter; cannot write LogUnitStop"); } } /** * Write the logStatement and its contents out through jsonWriter. * * Note that this method is not thread safe for the same jsonWriter. Callers must ensure * thread safety. */ private boolean outputLogStatementToLocked(final JsonWriter jsonWriter, final LogStatement logStatement, final Object[] values, final Long time) { if (DEBUG) { if (logStatement.getKeys().length != values.length) { Log.d(TAG, "Key and Value list sizes do not match. " + logStatement.getType()); } } try { jsonWriter.beginObject(); jsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis()); jsonWriter.name(UPTIME_KEY).value(time); jsonWriter.name(EVENT_TYPE_KEY).value(logStatement.getType()); final String[] keys = logStatement.getKeys(); final int length = values.length; for (int i = 0; i < length; i++) { jsonWriter.name(keys[i]); final Object value = values[i]; if (value instanceof CharSequence) { jsonWriter.value(value.toString()); } else if (value instanceof Number) { jsonWriter.value((Number) value); } else if (value instanceof Boolean) { jsonWriter.value((Boolean) value); } else if (value instanceof CompletionInfo[]) { JsonUtils.writeJson((CompletionInfo[]) value, jsonWriter); } else if (value instanceof SharedPreferences) { JsonUtils.writeJson((SharedPreferences) value, jsonWriter); } else if (value instanceof Key[]) { JsonUtils.writeJson((Key[]) value, jsonWriter); } else if (value instanceof SuggestedWords) { JsonUtils.writeJson((SuggestedWords) value, jsonWriter); } else if (value instanceof MotionEvent) { JsonUtils.writeJson((MotionEvent) value, jsonWriter); } else if (value == null) { jsonWriter.nullValue(); } else { Log.w(TAG, "Unrecognized type to be logged: " + (value == null ? "<null>" : value.getClass().getName())); jsonWriter.nullValue(); } } jsonWriter.endObject(); } catch (IOException e) { e.printStackTrace(); Log.w(TAG, "Error in JsonWriter; skipping LogStatement"); return false; } return true; LOGSTATEMENT_LOG_UNIT_END.outputToLocked(jsonWriter, SystemClock.uptimeMillis()); } /** Loading
java/src/com/android/inputmethod/research/ResearchLogger.java +11 −3 Original line number Diff line number Diff line Loading @@ -1003,15 +1003,23 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } /** * Publish all the logUnits in the logBuffer, without doing any privacy filtering. */ /* package for test */ void publishLogBuffer(final LogBuffer logBuffer, final ResearchLog researchLog, final boolean isIncludingPrivateData) { publishLogUnits(logBuffer.getLogUnits(), researchLog, isIncludingPrivateData); final ResearchLog researchLog, final boolean canIncludePrivateData) { publishLogUnits(logBuffer.getLogUnits(), researchLog, canIncludePrivateData); } private static final LogStatement LOGSTATEMENT_LOG_SEGMENT_OPENING = new LogStatement("logSegmentStart", false, false, "isIncludingPrivateData"); private static final LogStatement LOGSTATEMENT_LOG_SEGMENT_CLOSING = new LogStatement("logSegmentEnd", false, false); /** * Publish all LogUnits in a list. * * Any privacy checks should be performed before calling this method. */ /* package for test */ void publishLogUnits(final List<LogUnit> logUnits, final ResearchLog researchLog, final boolean canIncludePrivateData) { final LogUnit openingLogUnit = new LogUnit(); Loading Loading @@ -1392,7 +1400,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final int index, final String suggestion, final boolean isBatchMode) { final ResearchLogger researchLogger = getInstance(); if (!replacedWord.equals(suggestion.toString())) { // The user choose something other than what was already there. // The user chose something other than what was already there. researchLogger.setCurrentLogUnitContainsCorrection(); researchLogger.setCurrentLogUnitCorrectionType(LogUnit.CORRECTIONTYPE_TYPO); } Loading