am 7165f926: Merge "Refactor LogStatement publishing method"
# Via Android (Google) Code Review (1) and Kurt Partridge (1) * commit '7165f926b4304a033c2abae7f93a40156062a1a1': Refactor LogStatement publishing methodmain
commit
a023880bbc
|
@ -16,6 +16,18 @@
|
||||||
|
|
||||||
package com.android.inputmethod.research;
|
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.
|
* A template for typed information stored in the logs.
|
||||||
*
|
*
|
||||||
|
@ -24,6 +36,9 @@ package com.android.inputmethod.research;
|
||||||
* actual values are stored separately.
|
* actual values are stored separately.
|
||||||
*/
|
*/
|
||||||
class LogStatement {
|
class LogStatement {
|
||||||
|
private static final String TAG = LogStatement.class.getSimpleName();
|
||||||
|
private static final boolean DEBUG = false && ProductionFlag.IS_EXPERIMENTAL_DEBUG;
|
||||||
|
|
||||||
// Constants for particular statements
|
// Constants for particular statements
|
||||||
public static final String TYPE_POINTER_TRACKER_CALL_LISTENER_ON_CODE_INPUT =
|
public static final String TYPE_POINTER_TRACKER_CALL_LISTENER_ON_CODE_INPUT =
|
||||||
"PointerTrackerCallListenerOnCodeInput";
|
"PointerTrackerCallListenerOnCodeInput";
|
||||||
|
@ -36,6 +51,11 @@ class LogStatement {
|
||||||
public static final String TYPE_MOTION_EVENT = "MotionEvent";
|
public static final String TYPE_MOTION_EVENT = "MotionEvent";
|
||||||
public static final String KEY_IS_LOGGING_RELATED = "isLoggingRelated";
|
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.
|
// Name specifying the LogStatement type.
|
||||||
private final String mType;
|
private final String mType;
|
||||||
|
|
||||||
|
@ -142,4 +162,61 @@ class LogStatement {
|
||||||
}
|
}
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,11 @@
|
||||||
package com.android.inputmethod.research;
|
package com.android.inputmethod.research;
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.JsonWriter;
|
import android.util.JsonWriter;
|
||||||
import android.util.Log;
|
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;
|
||||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||||
import com.android.inputmethod.latin.define.ProductionFlag;
|
import com.android.inputmethod.latin.define.ProductionFlag;
|
||||||
|
@ -153,11 +151,10 @@ import java.util.List;
|
||||||
jsonWriter = researchLog.getValidJsonWriterLocked();
|
jsonWriter = researchLog.getValidJsonWriterLocked();
|
||||||
outputLogUnitStart(jsonWriter, canIncludePrivateData);
|
outputLogUnitStart(jsonWriter, canIncludePrivateData);
|
||||||
}
|
}
|
||||||
outputLogStatementToLocked(jsonWriter, mLogStatementList.get(i), mValuesList.get(i),
|
logStatement.outputToLocked(jsonWriter, mTimeList.get(i), mValuesList.get(i));
|
||||||
mTimeList.get(i));
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
outputLogStatementToLocked(debugJsonWriter, mLogStatementList.get(i),
|
logStatement.outputToLocked(debugJsonWriter, mTimeList.get(i),
|
||||||
mValuesList.get(i), mTimeList.get(i));
|
mValuesList.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (jsonWriter != null) {
|
if (jsonWriter != null) {
|
||||||
|
@ -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 WORD_KEY = "_wo";
|
||||||
private static final String CORRECTION_TYPE_KEY = "_corType";
|
private static final String CORRECTION_TYPE_KEY = "_corType";
|
||||||
private static final String LOG_UNIT_BEGIN_KEY = "logUnitStart";
|
private static final String LOG_UNIT_BEGIN_KEY = "logUnitStart";
|
||||||
private static final String LOG_UNIT_END_KEY = "logUnitEnd";
|
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,
|
private void outputLogUnitStart(final JsonWriter jsonWriter,
|
||||||
final boolean canIncludePrivateData) {
|
final boolean canIncludePrivateData) {
|
||||||
try {
|
final LogStatement logStatement;
|
||||||
jsonWriter.beginObject();
|
if (canIncludePrivateData) {
|
||||||
jsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis());
|
LOGSTATEMENT_LOG_UNIT_BEGIN_WITH_PRIVATE_DATA.outputToLocked(jsonWriter,
|
||||||
if (canIncludePrivateData) {
|
SystemClock.uptimeMillis(), getWord(), getCorrectionType());
|
||||||
jsonWriter.name(WORD_KEY).value(getWord());
|
} else {
|
||||||
jsonWriter.name(CORRECTION_TYPE_KEY).value(getCorrectionType());
|
LOGSTATEMENT_LOG_UNIT_BEGIN_WITHOUT_PRIVATE_DATA.outputToLocked(jsonWriter,
|
||||||
}
|
SystemClock.uptimeMillis());
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final LogStatement LOGSTATEMENT_LOG_UNIT_END =
|
||||||
|
new LogStatement(LOG_UNIT_END_KEY, false /* isPotentiallyPrivate */,
|
||||||
|
false /* isPotentiallyRevealing */);
|
||||||
private void outputLogUnitStop(final JsonWriter jsonWriter) {
|
private void outputLogUnitStop(final JsonWriter jsonWriter) {
|
||||||
try {
|
LOGSTATEMENT_LOG_UNIT_END.outputToLocked(jsonWriter, SystemClock.uptimeMillis());
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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,
|
/* package for test */ void publishLogBuffer(final LogBuffer logBuffer,
|
||||||
final ResearchLog researchLog, final boolean isIncludingPrivateData) {
|
final ResearchLog researchLog, final boolean canIncludePrivateData) {
|
||||||
publishLogUnits(logBuffer.getLogUnits(), researchLog, isIncludingPrivateData);
|
publishLogUnits(logBuffer.getLogUnits(), researchLog, canIncludePrivateData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final LogStatement LOGSTATEMENT_LOG_SEGMENT_OPENING =
|
private static final LogStatement LOGSTATEMENT_LOG_SEGMENT_OPENING =
|
||||||
new LogStatement("logSegmentStart", false, false, "isIncludingPrivateData");
|
new LogStatement("logSegmentStart", false, false, "isIncludingPrivateData");
|
||||||
private static final LogStatement LOGSTATEMENT_LOG_SEGMENT_CLOSING =
|
private static final LogStatement LOGSTATEMENT_LOG_SEGMENT_CLOSING =
|
||||||
new LogStatement("logSegmentEnd", false, false);
|
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,
|
/* package for test */ void publishLogUnits(final List<LogUnit> logUnits,
|
||||||
final ResearchLog researchLog, final boolean canIncludePrivateData) {
|
final ResearchLog researchLog, final boolean canIncludePrivateData) {
|
||||||
final LogUnit openingLogUnit = new LogUnit();
|
final LogUnit openingLogUnit = new LogUnit();
|
||||||
|
@ -1392,7 +1400,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
final int index, final String suggestion, final boolean isBatchMode) {
|
final int index, final String suggestion, final boolean isBatchMode) {
|
||||||
final ResearchLogger researchLogger = getInstance();
|
final ResearchLogger researchLogger = getInstance();
|
||||||
if (!replacedWord.equals(suggestion.toString())) {
|
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.setCurrentLogUnitContainsCorrection();
|
||||||
researchLogger.setCurrentLogUnitCorrectionType(LogUnit.CORRECTIONTYPE_TYPO);
|
researchLogger.setCurrentLogUnitCorrectionType(LogUnit.CORRECTIONTYPE_TYPO);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue