Merge "add more data collection points to ResearchLogger (attempt #2)"

This commit is contained in:
Kurt Partridge 2012-04-09 16:13:47 -07:00 committed by Android (Google) Code Review
commit 98986c6a43
8 changed files with 512 additions and 75 deletions

View file

@ -555,6 +555,9 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
* method on the base class if the subclass doesn't wish to handle the call.
*/
protected boolean onLongPress(Key parentKey, PointerTracker tracker) {
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinKeyboardView_onLongPress();
}
final int primaryCode = parentKey.mCode;
if (parentKey.hasEmbeddedMoreKey()) {
final int embeddedCode = KeySpecParser.getCode(getResources(), parentKey.mMoreKeys[0]);
@ -695,17 +698,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
}
}
if (ProductionFlag.IS_EXPERIMENTAL) {
if (ResearchLogger.sIsLogging) {
// TODO: remove redundant calculations of size and pressure by
// removing UsabilityStudyLog code once the ResearchLogger is mature enough
final float size = me.getSize(index);
final float pressure = me.getPressure(index);
if (action != MotionEvent.ACTION_MOVE) {
// Skip ACTION_MOVE events as they are logged below
ResearchLogger.getInstance().logMotionEvent(action, eventTime, id, x, y,
size, pressure);
}
}
ResearchLogger.latinKeyboardView_processMotionEvent(me, action, eventTime, index, id,
x, y);
}
if (mKeyTimerHandler.isInKeyRepeat()) {
@ -773,13 +767,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
+ pointerSize + "," + pointerPressure);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
if (ResearchLogger.sIsLogging) {
// TODO: earlier comment about redundant calculations applies here too
final float pointerSize = me.getSize(i);
final float pointerPressure = me.getPressure(i);
ResearchLogger.getInstance().logMotionEvent(action, eventTime, pointerId,
px, py, pointerSize, pointerPressure);
}
ResearchLogger.latinKeyboardView_processMotionEvent(me, action, eventTime,
i, pointerId, px, py);
}
}
} else {

View file

@ -23,6 +23,8 @@ import android.widget.TextView;
import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.ResearchLogger;
import com.android.inputmethod.latin.define.ProductionFlag;
import java.util.ArrayList;
@ -235,6 +237,10 @@ public class PointerTracker {
+ " ignoreModifier=" + ignoreModifierKey
+ " enabled=" + key.isEnabled());
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange(key,
ignoreModifierKey);
}
if (ignoreModifierKey) {
return false;
}
@ -259,6 +265,10 @@ public class PointerTracker {
+ " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode
+ " enabled=" + key.isEnabled());
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.pointerTracker_callListenerOnCodeInput(key, x, y, ignoreModifierKey,
altersCode, code);
}
if (ignoreModifierKey) {
return;
}
@ -284,6 +294,10 @@ public class PointerTracker {
+ " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey
+ " enabled="+ key.isEnabled());
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.pointerTracker_callListenerOnRelease(key, primaryCode, withSliding,
ignoreModifierKey);
}
if (ignoreModifierKey) {
return;
}
@ -295,6 +309,9 @@ public class PointerTracker {
private void callListenerOnCancelInput() {
if (DEBUG_LISTENER)
Log.d(TAG, "onCancelInput");
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.pointerTracker_callListenerOnCancelInput();
}
mListener.onCancelInput();
}
@ -479,6 +496,9 @@ public class PointerTracker {
if (DEBUG_MODE)
Log.w(TAG, "onDownEvent: ignore potential noise: time=" + deltaT
+ " distance=" + distanceSquared);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.pointerTracker_onDownEvent(deltaT, distanceSquared);
}
mKeyAlreadyProcessed = true;
return;
}
@ -583,6 +603,9 @@ public class PointerTracker {
if (DEBUG_MODE)
Log.w(TAG, String.format("onMoveEvent: sudden move is translated to "
+ "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y));
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.pointerTracker_onMoveEvent(x, y, lastX, lastY);
}
onUpEventInternal(lastX, lastY, eventTime);
onDownEventInternal(x, y, eventTime);
} else {

View file

@ -22,7 +22,9 @@ import android.view.MotionEvent;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.ResearchLogger;
import com.android.inputmethod.latin.Utils;
import com.android.inputmethod.latin.define.ProductionFlag;
public class SuddenJumpingTouchEventHandler {
private static final String TAG = SuddenJumpingTouchEventHandler.class.getSimpleName();
@ -141,6 +143,9 @@ public class SuddenJumpingTouchEventHandler {
if (handleSuddenJumping(me)) {
if (DEBUG_MODE)
Log.w(TAG, "onTouchEvent: ignore sudden jump " + me);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.suddenJumpingTouchEventHandler_onTouchEvent(me);
}
return true;
}
return mView.processMotionEvent(me);

View file

@ -18,6 +18,9 @@ package com.android.inputmethod.keyboard.internal;
import android.util.Log;
import com.android.inputmethod.latin.ResearchLogger;
import com.android.inputmethod.latin.define.ProductionFlag;
public class AlphabetShiftState {
private static final String TAG = AlphabetShiftState.class.getSimpleName();
private static final boolean DEBUG = false;
@ -59,6 +62,9 @@ public class AlphabetShiftState {
}
if (DEBUG)
Log.d(TAG, "setShifted(" + newShiftState + "): " + toString(oldState) + " > " + this);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.alphabetShiftState_setShifted(newShiftState, oldState, this);
}
}
public void setShiftLocked(boolean newShiftLockState) {
@ -78,6 +84,9 @@ public class AlphabetShiftState {
if (DEBUG)
Log.d(TAG, "setShiftLocked(" + newShiftLockState + "): " + toString(oldState)
+ " > " + this);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.alphabetShiftState_setShiftLocked(newShiftLockState, oldState, this);
}
}
public void setAutomaticShifted() {
@ -85,6 +94,9 @@ public class AlphabetShiftState {
mState = AUTOMATIC_SHIFTED;
if (DEBUG)
Log.d(TAG, "setAutomaticShifted: " + toString(oldState) + " > " + this);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.alphabetShiftState_setAutomaticShifted(oldState, this);
}
}
public boolean isShiftedOrShiftLocked() {

View file

@ -20,6 +20,8 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.ResearchLogger;
import com.android.inputmethod.latin.define.ProductionFlag;
/**
* Keyboard state machine.
@ -139,6 +141,9 @@ public class KeyboardState {
if (DEBUG_EVENT) {
Log.d(TAG, "onSaveKeyboardState: saved=" + state + " " + this);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.keyboardState_onSaveKeyboardState(this, state.toString());
}
}
private void onRestoreKeyboardState() {
@ -146,6 +151,9 @@ public class KeyboardState {
if (DEBUG_EVENT) {
Log.d(TAG, "onRestoreKeyboardState: saved=" + state + " " + this);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.keyboardState_onRestoreKeyboardState(this, state.toString());
}
if (!state.mIsValid || state.mIsAlphabetMode) {
setAlphabetKeyboard();
} else {
@ -178,6 +186,9 @@ public class KeyboardState {
if (DEBUG_ACTION) {
Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode) + " " + this);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.keyboardState_setShifted(this, shiftModeToString(shiftMode));
}
if (!mIsAlphabetMode) return;
final int prevShiftMode;
if (mAlphabetShiftState.isAutomaticShifted()) {
@ -217,6 +228,9 @@ public class KeyboardState {
if (DEBUG_ACTION) {
Log.d(TAG, "setShiftLocked: shiftLocked=" + shiftLocked + " " + this);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.keyboardState_setShiftLocked(this, shiftLocked);
}
if (!mIsAlphabetMode) return;
if (shiftLocked && (!mAlphabetShiftState.isShiftLocked()
|| mAlphabetShiftState.isShiftLockShifted())) {
@ -232,6 +246,9 @@ public class KeyboardState {
if (DEBUG_ACTION) {
Log.d(TAG, "toggleAlphabetAndSymbols: " + this);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.keyboardState_toggleAlphabetAndSymbols(this);
}
if (mIsAlphabetMode) {
mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked();
if (mPrevSymbolsKeyboardWasShifted) {
@ -262,6 +279,10 @@ public class KeyboardState {
if (DEBUG_ACTION) {
Log.d(TAG, "setAlphabetKeyboard");
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.keyboardState_setAlphabetKeyboard();
}
mSwitchActions.setAlphabetKeyboard();
mIsAlphabetMode = true;
mIsSymbolShifted = false;
@ -273,6 +294,9 @@ public class KeyboardState {
if (DEBUG_ACTION) {
Log.d(TAG, "setSymbolsKeyboard");
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.keyboardState_setSymbolsKeyboard();
}
mSwitchActions.setSymbolsKeyboard();
mIsAlphabetMode = false;
mIsSymbolShifted = false;
@ -285,6 +309,9 @@ public class KeyboardState {
if (DEBUG_ACTION) {
Log.d(TAG, "setSymbolsShiftedKeyboard");
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.keyboardState_setSymbolsShiftedKeyboard();
}
mSwitchActions.setSymbolsShiftedKeyboard();
mIsAlphabetMode = false;
mIsSymbolShifted = true;
@ -297,6 +324,9 @@ public class KeyboardState {
if (DEBUG_EVENT) {
Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code) + " " + this);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.keyboardState_onPressKey(code, this);
}
if (code == Keyboard.CODE_SHIFT) {
onPressShift();
} else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
@ -314,6 +344,9 @@ public class KeyboardState {
Log.d(TAG, "onReleaseKey: code=" + Keyboard.printableCode(code)
+ " sliding=" + withSliding + " " + this);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.keyboardState_onReleaseKey(this, code, withSliding);
}
if (code == Keyboard.CODE_SHIFT) {
onReleaseShift(withSliding);
} else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
@ -345,6 +378,9 @@ public class KeyboardState {
if (DEBUG_EVENT) {
Log.d(TAG, "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + this);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.keyboardState_onLongPressTimeout(code, this);
}
if (mIsAlphabetMode && code == Keyboard.CODE_SHIFT) {
if (mAlphabetShiftState.isShiftLocked()) {
setShiftLocked(false);
@ -363,6 +399,9 @@ public class KeyboardState {
if (DEBUG_EVENT) {
Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.keyboardState_onUpdateShiftState(this, autoCaps);
}
updateAlphabetShiftState(autoCaps);
}
@ -481,6 +520,9 @@ public class KeyboardState {
if (DEBUG_EVENT) {
Log.d(TAG, "onCancelInput: single=" + isSinglePointer + " " + this);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.keyboardState_onCancelInput(isSinglePointer, this);
}
// Switch back to the previous keyboard mode if the user cancels sliding input.
if (isSinglePointer) {
if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) {
@ -512,6 +554,9 @@ public class KeyboardState {
+ " single=" + isSinglePointer
+ " autoCaps=" + autoCaps + " " + this);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.keyboardState_onCodeInput(code, isSinglePointer, autoCaps, this);
}
switch (mSwitchState) {
case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL:

View file

@ -21,6 +21,8 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import android.text.TextUtils;
import android.util.Log;
import com.android.inputmethod.latin.define.ProductionFlag;
import java.util.ArrayList;
import java.util.HashMap;
@ -115,10 +117,19 @@ public class AutoCorrection {
+ autoCorrectionSuggestionScore + ", " + normalizedScore
+ "(" + autoCorrectionThreshold + ")");
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.autoCorrection_hasAutoCorrectionForBinaryDictionary(consideredWord,
autoCorrectionThreshold, autoCorrectionSuggestion.toString(),
autoCorrectionSuggestionScore, normalizedScore);
}
if (normalizedScore >= autoCorrectionThreshold) {
if (DBG) {
Log.d(TAG, "Auto corrected by S-threshold.");
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger
.autoCorrection_hasAutoCorrectionForBinaryDictionary_bySthreshold();
}
return true;
}
}

View file

@ -665,6 +665,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
+ String.format("inputType=0x%08x imeOptions=0x%08x",
editorInfo.inputType, editorInfo.imeOptions));
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_onStartInputViewInternal(editorInfo);
}
if (StringUtils.inPrivateImeOptions(null, IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)) {
Log.w(TAG, "Deprecated private IME option specified: "
+ editorInfo.privateImeOptions);
@ -762,19 +765,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
composingSpanStart, composingSpanEnd);
if (ProductionFlag.IS_EXPERIMENTAL) {
if (ResearchLogger.UnsLogGroup.ON_UPDATE_SELECTION.isEnabled) {
final String s = "onUpdateSelection: oss=" + oldSelStart
+ ", ose=" + oldSelEnd
+ ", lss=" + mLastSelectionStart
+ ", lse=" + mLastSelectionEnd
+ ", nss=" + newSelStart
+ ", nse=" + newSelEnd
+ ", cs=" + composingSpanStart
+ ", ce=" + composingSpanEnd;
ResearchLogger.logUnstructured(ResearchLogger.UnsLogGroup.ON_UPDATE_SELECTION, s);
}
}
if (DEBUG) {
Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart
+ ", ose=" + oldSelEnd
@ -785,6 +775,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
+ ", cs=" + composingSpanStart
+ ", ce=" + composingSpanEnd);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_onUpdateSelection(mLastSelectionStart, mLastSelectionEnd,
oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart,
composingSpanEnd);
}
// TODO: refactor the following code to be less contrived.
// "newSelStart != composingSpanEnd" || "newSelEnd != composingSpanEnd" means
@ -886,6 +881,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions);
}
if (mInputAttributes.mApplicationSpecifiedCompletionOn) {
mApplicationSpecifiedCompletions = applicationSpecifiedCompletions;
if (applicationSpecifiedCompletions == null) {
@ -1660,6 +1658,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (DEBUG) {
Log.d(TAG, "Switch to keyboard view.");
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_switchToKeyboardView();
}
View v = mKeyboardSwitcher.getKeyboardView();
if (v != null) {
// Confirms that the keyboard view doesn't have parent view.

View file

@ -25,15 +25,20 @@ import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import android.view.MotionEvent;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.KeyDetector;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.internal.AlphabetShiftState;
import com.android.inputmethod.keyboard.internal.KeyboardState;
import com.android.inputmethod.latin.define.ProductionFlag;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Logs the use of the LatinIME keyboard.
@ -46,13 +51,12 @@ import java.util.Date;
public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = ResearchLogger.class.getSimpleName();
private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
private static final boolean DEBUG = false;
private static final ResearchLogger sInstance = new ResearchLogger(new LogFileManager());
public static boolean sIsLogging = false;
/* package */ final Handler mLoggingHandler;
private InputMethodService mIms;
private final Date mDate;
private final SimpleDateFormat mDateFormat;
/**
* Isolates management of files. This variable should never be null, but can be changed
@ -79,35 +83,36 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
/* package */ LogFileManager() {
}
public void init(InputMethodService ims) {
public void init(final InputMethodService ims) {
mIms = ims;
}
public synchronized void createLogFile() {
public synchronized boolean createLogFile() {
try {
createLogFile(DEFAULT_LOG_DIRECTORY, DEFAULT_FILENAME);
} catch (FileNotFoundException e) {
return createLogFile(DEFAULT_LOG_DIRECTORY, DEFAULT_FILENAME);
} catch (final FileNotFoundException e) {
Log.w(TAG, e);
return false;
}
}
public synchronized void createLogFile(String dir, String filename)
public synchronized boolean createLogFile(final String dir, final String filename)
throws FileNotFoundException {
if (mIms == null) {
Log.w(TAG, "InputMethodService is not configured. Logging is off.");
return;
return false;
}
File filesDir = mIms.getFilesDir();
final File filesDir = mIms.getFilesDir();
if (filesDir == null || !filesDir.exists()) {
Log.w(TAG, "Storage directory does not exist. Logging is off.");
return;
return false;
}
File directory = new File(filesDir, dir);
final File directory = new File(filesDir, dir);
if (!directory.exists()) {
boolean wasCreated = directory.mkdirs();
final boolean wasCreated = directory.mkdirs();
if (!wasCreated) {
Log.w(TAG, "Log directory cannot be created. Logging is off.");
return;
return false;
}
}
@ -120,16 +125,23 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
append = false;
}
mPrintWriter = new PrintWriter(new FileOutputStream(mFile, append), true);
return true;
}
public synchronized boolean append(String s) {
public synchronized boolean append(final String s) {
if (mPrintWriter == null) {
Log.w(TAG, "PrintWriter is null");
return false;
} else {
mPrintWriter.print(s);
return !mPrintWriter.checkError();
if (DEBUG) {
Log.w(TAG, "PrintWriter is null... attempting to create default log file");
}
if (!createLogFile()) {
if (DEBUG) {
Log.w(TAG, "Failed to create log file. Not logging.");
return false;
}
}
}
mPrintWriter.print(s);
return !mPrintWriter.checkError();
}
public synchronized void reset() {
@ -152,11 +164,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
}
private ResearchLogger(LogFileManager logFileManager) {
mDate = new Date();
mDateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss.SSSZ");
HandlerThread handlerThread = new HandlerThread("ResearchLogger logging task",
private ResearchLogger(final LogFileManager logFileManager) {
final HandlerThread handlerThread = new HandlerThread("ResearchLogger logging task",
Process.THREAD_PRIORITY_BACKGROUND);
handlerThread.start();
mLoggingHandler = new Handler(handlerThread.getLooper());
@ -167,11 +176,11 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
return sInstance;
}
public static void init(InputMethodService ims, SharedPreferences prefs) {
public static void init(final InputMethodService ims, final SharedPreferences prefs) {
sInstance.initInternal(ims, prefs);
}
public void initInternal(InputMethodService ims, SharedPreferences prefs) {
public void initInternal(final InputMethodService ims, final SharedPreferences prefs) {
mIms = ims;
if (mLogFileManager != null) {
mLogFileManager.init(ims);
@ -188,7 +197,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
*
* @throws IllegalArgumentException if logFileManager is null
*/
void setLogFileManager(LogFileManager manager) {
void setLogFileManager(final LogFileManager manager) {
if (manager == null) {
throw new IllegalArgumentException("warning: trying to set null logFileManager");
} else {
@ -203,11 +212,12 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
MOTION_EVENT("m"),
KEY("k"),
CORRECTION("c"),
STATE_CHANGE("s");
STATE_CHANGE("s"),
UNSTRUCTURED("u");
private final String mLogString;
private LogGroup(String logString) {
private LogGroup(final String logString) {
mLogString = logString;
}
}
@ -226,7 +236,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
default: eventTag = "[Action" + action + "]"; break;
}
if (!TextUtils.isEmpty(eventTag)) {
StringBuilder sb = new StringBuilder();
final StringBuilder sb = new StringBuilder();
sb.append(eventTag);
sb.append('\t'); sb.append(eventTime);
sb.append('\t'); sb.append(id);
@ -238,7 +248,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
}
public void logKeyEvent(int code, int x, int y) {
public void logKeyEvent(final int code, final int x, final int y) {
final StringBuilder sb = new StringBuilder();
sb.append(Keyboard.printableCode(code));
sb.append('\t'); sb.append(x);
@ -246,7 +256,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
write(LogGroup.KEY, sb.toString());
}
public void logCorrection(String subgroup, String before, String after, int position) {
public void logCorrection(final String subgroup, final String before, final String after,
final int position) {
final StringBuilder sb = new StringBuilder();
sb.append(subgroup);
sb.append('\t'); sb.append(before);
@ -255,19 +266,62 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
write(LogGroup.CORRECTION, sb.toString());
}
public void logStateChange(String subgroup, String details) {
public void logStateChange(final String subgroup, final String details) {
write(LogGroup.STATE_CHANGE, subgroup + "\t" + details);
}
public static enum UnsLogGroup {
// TODO: expand to include one flag per log point
// TODO: support selective enabling of flags
ON_UPDATE_SELECTION;
public static class UnsLogGroup {
private static final boolean DEFAULT_ENABLED = true;
public boolean isEnabled = true;
private static final boolean ALPHABETSHIFTSTATE_SETSHIFTED_ENABLED = DEFAULT_ENABLED;
private static final boolean ALPHABETSHIFTSTATE_SETSHIFTLOCKED_ENABLED = DEFAULT_ENABLED;
private static final boolean ALPHABETSHIFTSTATE_SETAUTOMATICSHIFTED_ENABLED
= DEFAULT_ENABLED;
private static final boolean AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_ENABLED
= DEFAULT_ENABLED;
private static final boolean
AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_BYSTHRESHOLD_ENABLED
= DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_ONCANCELINPUT_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_ONCODEINPUT_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_ONPRESSKEY_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_ONRELEASEKEY_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_ONRESTOREKEYBOARDSTATE_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_ONSAVEKEYBOARDSTATE_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_ONUPDATESHIFTSTATE_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_SETALPHABETKEYBOARD_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_SETSHIFTED_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_SETSHIFTLOCKED_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_SETSYMBOLSKEYBOARD_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_SETSYMBOLSSHIFTEDKEYBOARD_ENABLED
= DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED
= DEFAULT_ENABLED;
private static final boolean LATINIME_ONDISPLAYCOMPLETIONS_ENABLED = DEFAULT_ENABLED;
private static final boolean LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED = DEFAULT_ENABLED;
private static final boolean LATINIME_ONUPDATESELECTION_ENABLED = DEFAULT_ENABLED;
private static final boolean LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED = DEFAULT_ENABLED;
private static final boolean LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED = DEFAULT_ENABLED;
private static final boolean LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED
= DEFAULT_ENABLED;
private static final boolean POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED
= DEFAULT_ENABLED;
private static final boolean POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED
= DEFAULT_ENABLED;
private static final boolean
POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED
= DEFAULT_ENABLED;
private static final boolean POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED = DEFAULT_ENABLED;
private static final boolean POINTERTRACKER_ONDOWNEVENT_ENABLED = DEFAULT_ENABLED;
private static final boolean POINTERTRACKER_ONMOVEEVENT_ENABLED = DEFAULT_ENABLED;
private static final boolean SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED
= DEFAULT_ENABLED;
}
public static void logUnstructured(UnsLogGroup logGroup, String details) {
public static void logUnstructured(String logGroup, final String details) {
// TODO: improve performance by making entire class static and/or implementing natively
getInstance().write(LogGroup.UNSTRUCTURED, logGroup + "\t" + details);
}
private void write(final LogGroup logGroup, final String log) {
@ -282,13 +336,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
builder.append('\t'); builder.append(upTime);
builder.append('\t'); builder.append(logGroup.mLogString);
builder.append('\t'); builder.append(log);
if (LatinImeLogger.sDBG) {
builder.append('\n');
if (DEBUG) {
Log.d(TAG, "Write: " + '[' + logGroup.mLogString + ']' + log);
}
if (mLogFileManager.append(builder.toString())) {
// success
} else {
if (LatinImeLogger.sDBG) {
if (DEBUG) {
Log.w(TAG, "Unable to write to log.");
}
}
@ -300,7 +355,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
mLoggingHandler.post(new Runnable() {
@Override
public void run() {
if (LatinImeLogger.sDBG) {
if (DEBUG) {
Log.d(TAG, "Delete log file.");
}
mLogFileManager.reset();
@ -315,4 +370,300 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false);
}
public static void alphabetShiftState_setShifted(final boolean newShiftState,
final int oldState, final AlphabetShiftState alphabetShiftState) {
if (UnsLogGroup.ALPHABETSHIFTSTATE_SETSHIFTED_ENABLED) {
final String s = "setShifted(" + newShiftState + "): " + oldState
+ " > " + alphabetShiftState;
logUnstructured("AlphabetShiftState_setShifted", s);
}
}
public static void alphabetShiftState_setShiftLocked(final boolean newShiftLockState,
final int oldState, final AlphabetShiftState alphabetShiftState) {
if (UnsLogGroup.ALPHABETSHIFTSTATE_SETSHIFTLOCKED_ENABLED) {
final String s = "setShiftLocked(" + newShiftLockState + "): "
+ oldState + " > " + alphabetShiftState;
logUnstructured("AlphabetShiftState_setShiftLocked", s);
}
}
public static void alphabetShiftState_setAutomaticShifted(final int oldState,
final AlphabetShiftState alphabetShiftState) {
if (UnsLogGroup.ALPHABETSHIFTSTATE_SETAUTOMATICSHIFTED_ENABLED) {
final String s = "setAutomaticShifted: " + oldState + " > " + alphabetShiftState;
logUnstructured("AlphabetShiftState_setAutomaticShifted", s);
}
}
public static void autoCorrection_hasAutoCorrectionForBinaryDictionary(
final CharSequence consideredWord, final double autoCorrectionThreshold,
final CharSequence autoCorrectionSuggestion, final int autoCorrectionSuggestionScore,
final double normalizedScore) {
if (UnsLogGroup.AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_ENABLED) {
final String s = "Normalized " + consideredWord + ","
+ autoCorrectionSuggestion + "," + autoCorrectionSuggestionScore
+ ", " + normalizedScore + "(" + autoCorrectionThreshold + ")";
logUnstructured("AutoCorrection_hasAutoCorrectionForBinaryDictionary", s);
}
}
public static void autoCorrection_hasAutoCorrectionForBinaryDictionary_bySthreshold() {
if (UnsLogGroup.AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_BYSTHRESHOLD_ENABLED) {
final String s = "Auto corrected by S-threshold.";
logUnstructured("AutoCorrection_hasAutoCorrectionForBinaryDictionar_bySthreshold", s);
}
}
public static void keyboardState_onCancelInput(final boolean isSinglePointer,
final KeyboardState keyboardState) {
if (UnsLogGroup.KEYBOARDSTATE_ONCANCELINPUT_ENABLED) {
final String s = "onCancelInput: single=" + isSinglePointer + " " + keyboardState;
logUnstructured("KeyboardState_onCancelInput", s);
}
}
public static void keyboardState_onCodeInput(
final int code, final boolean isSinglePointer, final boolean autoCaps,
final KeyboardState keyboardState) {
if (UnsLogGroup.KEYBOARDSTATE_ONCODEINPUT_ENABLED) {
final String s = "onCodeInput: code=" + Keyboard.printableCode(code)
+ " single=" + isSinglePointer
+ " autoCaps=" + autoCaps + " " + keyboardState;
logUnstructured("KeyboardState_onCodeInput", s);
}
}
public static void keyboardState_onLongPressTimeout(final int code,
final KeyboardState keyboardState) {
if (UnsLogGroup.KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED) {
final String s = "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " "
+ keyboardState;
logUnstructured("KeyboardState_onLongPressTimeout", s);
}
}
public static void keyboardState_onPressKey(final int code,
final KeyboardState keyboardState) {
if (UnsLogGroup.KEYBOARDSTATE_ONPRESSKEY_ENABLED) {
final String s = "onPressKey: code=" + Keyboard.printableCode(code) + " "
+ keyboardState;
logUnstructured("KeyboardState_onPressKey", s);
}
}
public static void keyboardState_onReleaseKey(final KeyboardState keyboardState, final int code,
final boolean withSliding) {
if (UnsLogGroup.KEYBOARDSTATE_ONRELEASEKEY_ENABLED) {
final String s = "onReleaseKey: code=" + Keyboard.printableCode(code)
+ " sliding=" + withSliding + " " + keyboardState;
logUnstructured("KeyboardState_onReleaseKey", s);
}
}
public static void keyboardState_onRestoreKeyboardState(final KeyboardState keyboardState,
final String savedKeyboardState) {
if (UnsLogGroup.KEYBOARDSTATE_ONRESTOREKEYBOARDSTATE_ENABLED) {
final String s = "onRestoreKeyboardState: saved=" + savedKeyboardState + " "
+ keyboardState;
logUnstructured("KeyboardState_onRestoreKeyboardState", s);
}
}
public static void keyboardState_onSaveKeyboardState(final KeyboardState keyboardState,
final String savedKeyboardState) {
if (UnsLogGroup.KEYBOARDSTATE_ONSAVEKEYBOARDSTATE_ENABLED) {
final String s = "onSaveKeyboardState: saved=" + savedKeyboardState + " "
+ keyboardState;
logUnstructured("KeyboardState_onSaveKeyboardState", s);
}
}
public static void keyboardState_onUpdateShiftState(final KeyboardState keyboardState,
final boolean autoCaps) {
if (UnsLogGroup.KEYBOARDSTATE_ONUPDATESHIFTSTATE_ENABLED) {
final String s = "onUpdateShiftState: autoCaps=" + autoCaps + " " + keyboardState;
logUnstructured("KeyboardState_onUpdateShiftState", s);
}
}
public static void keyboardState_setAlphabetKeyboard() {
if (UnsLogGroup.KEYBOARDSTATE_SETALPHABETKEYBOARD_ENABLED) {
final String s = "setAlphabetKeyboard";
logUnstructured("KeyboardState_setAlphabetKeyboard", s);
}
}
public static void keyboardState_setShifted(final KeyboardState keyboardState,
final String shiftMode) {
if (UnsLogGroup.KEYBOARDSTATE_SETSHIFTED_ENABLED) {
final String s = "setShifted: shiftMode=" + shiftMode + " " + keyboardState;
logUnstructured("KeyboardState_setShifted", s);
}
}
public static void keyboardState_setShiftLocked(final KeyboardState keyboardState,
final boolean shiftLocked) {
if (UnsLogGroup.KEYBOARDSTATE_SETSHIFTLOCKED_ENABLED) {
final String s = "setShiftLocked: shiftLocked=" + shiftLocked + " " + keyboardState;
logUnstructured("KeyboardState_setShiftLocked", s);
}
}
public static void keyboardState_setSymbolsKeyboard() {
if (UnsLogGroup.KEYBOARDSTATE_SETSYMBOLSKEYBOARD_ENABLED) {
final String s = "setSymbolsKeyboard";
logUnstructured("KeyboardState_setSymbolsKeyboard", s);
}
}
public static void keyboardState_setSymbolsShiftedKeyboard() {
if (UnsLogGroup.KEYBOARDSTATE_SETSYMBOLSSHIFTEDKEYBOARD_ENABLED) {
final String s = "setSymbolsShiftedKeyboard";
logUnstructured("KeyboardState_setSymbolsShiftedKeyboard", s);
}
}
public static void keyboardState_toggleAlphabetAndSymbols(final KeyboardState keyboardState) {
if (UnsLogGroup.KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED) {
final String s = "toggleAlphabetAndSymbols: " + keyboardState;
logUnstructured("KeyboardState_toggleAlphabetAndSymbols", s);
}
}
public static void latinIME_onDisplayCompletions(
final CompletionInfo[] applicationSpecifiedCompletions) {
if (UnsLogGroup.LATINIME_ONDISPLAYCOMPLETIONS_ENABLED) {
final StringBuilder builder = new StringBuilder();
builder.append("Received completions:");
if (applicationSpecifiedCompletions != null) {
for (int i = 0; i < applicationSpecifiedCompletions.length; i++) {
builder.append(" #");
builder.append(i);
builder.append(": ");
builder.append(applicationSpecifiedCompletions[i]);
builder.append("\n");
}
}
logUnstructured("LatinIME_onDisplayCompletions", builder.toString());
}
}
public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo) {
if (UnsLogGroup.LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED) {
final StringBuilder builder = new StringBuilder();
builder.append("onStartInputView: editorInfo:");
builder.append("inputType=");
builder.append(editorInfo.inputType);
builder.append("imeOptions=");
builder.append(editorInfo.imeOptions);
logUnstructured("LatinIME_onStartInputViewInternal", builder.toString());
}
}
public static void latinIME_onUpdateSelection(final int lastSelectionStart,
final int lastSelectionEnd, final int oldSelStart, final int oldSelEnd,
final int newSelStart, final int newSelEnd, final int composingSpanStart,
final int composingSpanEnd) {
if (UnsLogGroup.LATINIME_ONUPDATESELECTION_ENABLED) {
final String s = "onUpdateSelection: oss=" + oldSelStart
+ ", ose=" + oldSelEnd
+ ", lss=" + lastSelectionStart
+ ", lse=" + lastSelectionEnd
+ ", nss=" + newSelStart
+ ", nse=" + newSelEnd
+ ", cs=" + composingSpanStart
+ ", ce=" + composingSpanEnd;
logUnstructured("LatinIME_onUpdateSelection", s);
}
}
public static void latinIME_switchToKeyboardView() {
if (UnsLogGroup.LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED) {
final String s = "Switch to keyboard view.";
logUnstructured("LatinIME_switchToKeyboardView", s);
}
}
public static void latinKeyboardView_onLongPress() {
if (UnsLogGroup.LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED) {
final String s = "long press detected";
logUnstructured("LatinKeyboardView_onLongPress", s);
}
}
public static void latinKeyboardView_processMotionEvent(MotionEvent me, int action,
long eventTime, int index, int id, int x, int y) {
if (UnsLogGroup.LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED) {
final float size = me.getSize(index);
final float pressure = me.getPressure(index);
if (action != MotionEvent.ACTION_MOVE) {
getInstance().logMotionEvent(action, eventTime, id, x, y, size, pressure);
}
}
}
public static void pointerTracker_callListenerOnCancelInput() {
final String s = "onCancelInput";
if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED) {
logUnstructured("PointerTracker_callListenerOnCancelInput", s);
}
}
public static void pointerTracker_callListenerOnCodeInput(final Key key, final int x,
final int y, final boolean ignoreModifierKey, final boolean altersCode,
final int code) {
if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED) {
final String s = "onCodeInput: " + Keyboard.printableCode(code)
+ " text=" + key.mOutputText + " x=" + x + " y=" + y
+ " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode
+ " enabled=" + key.isEnabled();
logUnstructured("PointerTracker_callListenerOnCodeInput", s);
}
}
public static void pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange(
final Key key, final boolean ignoreModifierKey) {
if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED) {
final String s = "onPress : " + KeyDetector.printableCode(key)
+ " ignoreModifier=" + ignoreModifierKey
+ " enabled=" + key.isEnabled();
logUnstructured("PointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange", s);
}
}
public static void pointerTracker_callListenerOnRelease(final Key key, final int primaryCode,
final boolean withSliding, final boolean ignoreModifierKey) {
if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED) {
final String s = "onRelease : " + Keyboard.printableCode(primaryCode)
+ " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey
+ " enabled="+ key.isEnabled();
logUnstructured("PointerTracker_callListenerOnRelease", s);
}
}
public static void pointerTracker_onDownEvent(long deltaT, int distanceSquared) {
if (UnsLogGroup.POINTERTRACKER_ONDOWNEVENT_ENABLED) {
final String s = "onDownEvent: ignore potential noise: time=" + deltaT
+ " distance=" + distanceSquared;
logUnstructured("PointerTracker_onDownEvent", s);
}
}
public static void pointerTracker_onMoveEvent(final int x, final int y, final int lastX,
final int lastY) {
if (UnsLogGroup.POINTERTRACKER_ONMOVEEVENT_ENABLED) {
final String s = String.format("onMoveEvent: sudden move is translated to "
+ "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y);
logUnstructured("PointerTracker_onMoveEvent", s);
}
}
public static void suddenJumpingTouchEventHandler_onTouchEvent(final MotionEvent me) {
if (UnsLogGroup.SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED) {
final String s = "onTouchEvent: ignore sudden jump " + me;
logUnstructured("SuddenJumpingTouchEventHandler_onTouchEvent", s);
}
}
}