aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/research/ResearchLogger.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/research/ResearchLogger.java')
-rw-r--r--java/src/com/android/inputmethod/research/ResearchLogger.java321
1 files changed, 219 insertions, 102 deletions
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index dbf2d2982..c4d53e10a 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -39,6 +39,8 @@ import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.net.Uri;
import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
import android.os.SystemClock;
import android.preference.PreferenceManager;
@@ -57,6 +59,7 @@ import android.widget.Toast;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.KeyboardView;
import com.android.inputmethod.keyboard.MainKeyboardView;
import com.android.inputmethod.latin.Constants;
@@ -69,8 +72,17 @@ import com.android.inputmethod.latin.RichInputConnection.Range;
import com.android.inputmethod.latin.Suggest;
import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.define.ProductionFlag;
+import com.android.inputmethod.research.MotionEventReader.ReplayData;
+import java.io.BufferedReader;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
@@ -87,8 +99,18 @@ import java.util.UUID;
* This functionality is off by default. See {@link ProductionFlag#IS_EXPERIMENTAL}.
*/
public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener {
+ // TODO: This class has grown quite large and combines several concerns that should be
+ // separated. The following refactorings will be applied as soon as possible after adding
+ // support for replaying historical events, fixing some replay bugs, adding some ui constraints
+ // on the feedback dialog, and adding the survey dialog.
+ // TODO: Refactor. Move splash screen code into separate class.
+ // TODO: Refactor. Move feedback screen code into separate class.
+ // TODO: Refactor. Move logging invocations into their own class.
+ // TODO: Refactor. Move currentLogUnit management into separate class.
private static final String TAG = ResearchLogger.class.getSimpleName();
private static final boolean DEBUG = false && ProductionFlag.IS_EXPERIMENTAL_DEBUG;
+ private static final boolean DEBUG_REPLAY_AFTER_FEEDBACK = false
+ && ProductionFlag.IS_EXPERIMENTAL_DEBUG;
// Whether the TextView contents are logged at the end of the session. true will disclose
// private info.
private static final boolean LOG_FULL_TEXTVIEW_CONTENTS = false
@@ -98,8 +120,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
private static final int OUTPUT_FORMAT_VERSION = 5;
private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
private static final String PREF_RESEARCH_HAS_SEEN_SPLASH = "pref_research_has_seen_splash";
- /* package */ static final String FILENAME_PREFIX = "researchLog";
- private static final String FILENAME_SUFFIX = ".txt";
+ /* package */ static final String LOG_FILENAME_PREFIX = "researchLog";
+ private static final String LOG_FILENAME_SUFFIX = ".txt";
+ /* package */ static final String USER_RECORDING_FILENAME_PREFIX = "recording";
+ private static final String USER_RECORDING_FILENAME_SUFFIX = ".txt";
private static final SimpleDateFormat TIMESTAMP_DATEFORMAT =
new SimpleDateFormat("yyyyMMddHHmmssS", Locale.US);
// Whether to show an indicator on the screen that logging is on. Currently a very small red
@@ -129,9 +153,15 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
// the system to do so.
// LogUnits are queued in the LogBuffers and published to the ResearchLogs when words are
// complete.
- /* package */ ResearchLog mFeedbackLog;
/* package */ MainLogBuffer mMainLogBuffer;
+ // TODO: Remove the feedback log. The feedback log continuously captured user data in case the
+ // user wanted to submit it. We now use the mUserRecordingLogBuffer to allow the user to
+ // explicitly reproduce a problem.
+ /* package */ ResearchLog mFeedbackLog;
/* package */ LogBuffer mFeedbackLogBuffer;
+ /* package */ ResearchLog mUserRecordingLog;
+ /* package */ LogBuffer mUserRecordingLogBuffer;
+ private File mUserRecordingFile = null;
private boolean mIsPasswordView = false;
private boolean mIsLoggingSuspended = false;
@@ -144,7 +174,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
/* package for test */ static final String WORD_REPLACEMENT_STRING = "\uE001";
private static final String PREF_LAST_CLEANUP_TIME = "pref_last_cleanup_time";
private static final long DURATION_BETWEEN_DIR_CLEANUP_IN_MS = DateUtils.DAY_IN_MILLIS;
- private static final long MAX_LOGFILE_AGE_IN_MS = DateUtils.DAY_IN_MILLIS;
+ private static final long MAX_LOGFILE_AGE_IN_MS = 4 * DateUtils.DAY_IN_MILLIS;
protected static final int SUSPEND_DURATION_IN_MINUTES = 1;
// set when LatinIME should ignore an onUpdateSelection() callback that
// arises from operations in this class
@@ -153,10 +183,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
// used to check whether words are not unique
private Suggest mSuggest;
private MainKeyboardView mMainKeyboardView;
+ // TODO: Check whether a superclass can be used instead of LatinIME.
private LatinIME mLatinIME;
private final Statistics mStatistics;
+ private final MotionEventReader mMotionEventReader = new MotionEventReader();
+ private final Replayer mReplayer = new Replayer();
private Intent mUploadIntent;
+ private Intent mUploadNowIntent;
private LogUnit mCurrentLogUnit = new LogUnit();
@@ -165,6 +199,20 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
// thereby leaking private data, we store the time of the down event that started the second
// gesture, and when committing the earlier word, split the LogUnit.
private long mSavedDownEventTime;
+ private Bundle mFeedbackDialogBundle = null;
+ private boolean mInFeedbackDialog = false;
+ // The feedback dialog causes stop() to be called for the keyboard connected to the original
+ // window. This is because the feedback dialog must present its own EditText box that displays
+ // a keyboard. stop() normally causes mFeedbackLogBuffer, which contains the user's data, to be
+ // cleared, and causes mFeedbackLog, which is ready to collect information in case the user
+ // wants to upload, to be closed. This is good because we don't need to log information about
+ // what the user is typing in the feedback dialog, but bad because this data must be uploaded.
+ // Here we save the LogBuffer and Log so the feedback dialog can later access their data.
+ private LogBuffer mSavedFeedbackLogBuffer;
+ private ResearchLog mSavedFeedbackLog;
+ private Handler mUserRecordingTimeoutHandler;
+ private static final long USER_RECORDING_TIMEOUT_MS = 30L * DateUtils.SECOND_IN_MILLIS;
+
private ResearchLogger() {
mStatistics = Statistics.getInstance();
}
@@ -173,7 +221,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
return sInstance;
}
- public void init(final LatinIME latinIME) {
+ public void init(final LatinIME latinIME, final KeyboardSwitcher keyboardSwitcher) {
assert latinIME != null;
if (latinIME == null) {
Log.w(TAG, "IMS is null; logging is off");
@@ -210,6 +258,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
mLatinIME = latinIME;
mPrefs = prefs;
mUploadIntent = new Intent(mLatinIME, UploaderService.class);
+ mUploadNowIntent = new Intent(mLatinIME, UploaderService.class);
+ mUploadNowIntent.putExtra(UploaderService.EXTRA_UPLOAD_UNCONDITIONALLY, true);
+ mReplayer.setKeyboardSwitcher(keyboardSwitcher);
if (ProductionFlag.IS_EXPERIMENTAL) {
scheduleUploadingService(mLatinIME);
@@ -237,8 +288,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
private void cleanupLoggingDir(final File dir, final long time) {
for (File file : dir.listFiles()) {
- if (file.getName().startsWith(ResearchLogger.FILENAME_PREFIX) &&
- file.lastModified() < time) {
+ final String filename = file.getName();
+ if ((filename.startsWith(ResearchLogger.LOG_FILENAME_PREFIX)
+ || filename.startsWith(ResearchLogger.USER_RECORDING_FILENAME_PREFIX))
+ && file.lastModified() < time) {
file.delete();
}
}
@@ -335,9 +388,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
private static int sLogFileCounter = 0;
- private File createLogFile(File filesDir) {
+ private File createLogFile(final File filesDir) {
final StringBuilder sb = new StringBuilder();
- sb.append(FILENAME_PREFIX).append('-');
+ sb.append(LOG_FILENAME_PREFIX).append('-');
sb.append(mUUIDString).append('-');
sb.append(TIMESTAMP_DATEFORMAT.format(new Date())).append('-');
// Sometimes logFiles are created within milliseconds of each other. Append a counter to
@@ -349,7 +402,16 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
sLogFileCounter = 0;
}
sb.append(sLogFileCounter);
- sb.append(FILENAME_SUFFIX);
+ sb.append(LOG_FILENAME_SUFFIX);
+ return new File(filesDir, sb.toString());
+ }
+
+ private File createUserRecordingFile(final File filesDir) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(USER_RECORDING_FILENAME_PREFIX).append('-');
+ sb.append(mUUIDString).append('-');
+ sb.append(TIMESTAMP_DATEFORMAT.format(new Date()));
+ sb.append(USER_RECORDING_FILENAME_SUFFIX);
return new File(filesDir, sb.toString());
}
@@ -517,51 +579,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
presentFeedbackDialog(latinIME);
}
- // TODO: currently unreachable. Remove after being sure no menu is needed.
- /*
- public void presentResearchDialog(final LatinIME latinIME) {
- final CharSequence title = latinIME.getString(R.string.english_ime_research_log);
- final boolean showEnable = mIsLoggingSuspended || !sIsLogging;
- final CharSequence[] items = new CharSequence[] {
- latinIME.getString(R.string.research_feedback_menu_option),
- showEnable ? latinIME.getString(R.string.research_enable_session_logging) :
- latinIME.getString(R.string.research_do_not_log_this_session)
- };
- final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface di, int position) {
- di.dismiss();
- switch (position) {
- case 0:
- presentFeedbackDialog(latinIME);
- break;
- case 1:
- enableOrDisable(showEnable, latinIME);
- break;
- }
- }
-
- };
- final AlertDialog.Builder builder = new AlertDialog.Builder(latinIME)
- .setItems(items, listener)
- .setTitle(title);
- latinIME.showOptionDialog(builder.create());
- }
- */
-
- private boolean mInFeedbackDialog = false;
-
- // The feedback dialog causes stop() to be called for the keyboard connected to the original
- // window. This is because the feedback dialog must present its own EditText box that displays
- // a keyboard. stop() normally causes mFeedbackLogBuffer, which contains the user's data, to be
- // cleared, and causes mFeedbackLog, which is ready to collect information in case the user
- // wants to upload, to be closed. This is good because we don't need to log information about
- // what the user is typing in the feedback dialog, but bad because this data must be uploaded.
- // Here we save the LogBuffer and Log so the feedback dialog can later access their data.
- private LogBuffer mSavedFeedbackLogBuffer;
- private ResearchLog mSavedFeedbackLog;
-
public void presentFeedbackDialog(LatinIME latinIME) {
+ if (isMakingUserRecording()) {
+ saveRecording();
+ }
mInFeedbackDialog = true;
mSavedFeedbackLogBuffer = mFeedbackLogBuffer;
mSavedFeedbackLog = mFeedbackLog;
@@ -569,7 +590,90 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
// Feedback dialog will not close them.
mFeedbackLogBuffer = null;
mFeedbackLog = null;
- latinIME.launchKeyboardedDialogActivity(FeedbackActivity.class);
+
+ Intent intent = new Intent();
+ intent.setClass(mLatinIME, FeedbackActivity.class);
+ if (mFeedbackDialogBundle != null) {
+ Log.d(TAG, "putting extra in feedbackdialogbundle");
+ intent.putExtras(mFeedbackDialogBundle);
+ }
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ latinIME.startActivity(intent);
+ }
+
+ public void setFeedbackDialogBundle(final Bundle bundle) {
+ mFeedbackDialogBundle = bundle;
+ }
+
+ public void startRecording() {
+ final Resources res = mLatinIME.getResources();
+ Toast.makeText(mLatinIME,
+ res.getString(R.string.research_feedback_demonstration_instructions),
+ Toast.LENGTH_LONG).show();
+ startRecordingInternal();
+ }
+
+ private void startRecordingInternal() {
+ commitCurrentLogUnit();
+ if (mUserRecordingLog != null) {
+ mUserRecordingLog.abort();
+ }
+ mUserRecordingFile = createUserRecordingFile(mFilesDir);
+ mUserRecordingLog = new ResearchLog(mUserRecordingFile, mLatinIME);
+ mUserRecordingLogBuffer = new LogBuffer();
+ resetRecordingTimer();
+ }
+
+ private boolean isMakingUserRecording() {
+ return mUserRecordingLog != null;
+ }
+
+ private void resetRecordingTimer() {
+ if (mUserRecordingTimeoutHandler == null) {
+ mUserRecordingTimeoutHandler = new Handler();
+ }
+ clearRecordingTimer();
+ mUserRecordingTimeoutHandler.postDelayed(mRecordingHandlerTimeoutRunnable,
+ USER_RECORDING_TIMEOUT_MS);
+ }
+
+ private void clearRecordingTimer() {
+ mUserRecordingTimeoutHandler.removeCallbacks(mRecordingHandlerTimeoutRunnable);
+ }
+
+ private Runnable mRecordingHandlerTimeoutRunnable = new Runnable() {
+ @Override
+ public void run() {
+ cancelRecording();
+ requestIndicatorRedraw();
+ final Resources res = mLatinIME.getResources();
+ Toast.makeText(mLatinIME, res.getString(R.string.research_feedback_recording_failure),
+ Toast.LENGTH_LONG).show();
+ }
+ };
+
+ private void cancelRecording() {
+ if (mUserRecordingLog != null) {
+ mUserRecordingLog.abort();
+ }
+ mUserRecordingLog = null;
+ mUserRecordingLogBuffer = null;
+ if (mFeedbackDialogBundle != null) {
+ mFeedbackDialogBundle.putBoolean("HasRecording", false);
+ }
+ }
+
+ private void saveRecording() {
+ commitCurrentLogUnit();
+ publishLogBuffer(mUserRecordingLogBuffer, mUserRecordingLog, true);
+ mUserRecordingLog.close(null);
+ mUserRecordingLog = null;
+ mUserRecordingLogBuffer = null;
+
+ if (mFeedbackDialogBundle != null) {
+ mFeedbackDialogBundle.putBoolean(FeedbackFragment.KEY_HAS_USER_RECORDING, true);
+ }
+ clearRecordingTimer();
}
// TODO: currently unreachable. Remove after being sure enable/disable is
@@ -631,52 +735,39 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
return null;
}
- static class LogStatement {
- final String mName;
-
- // mIsPotentiallyPrivate indicates that event contains potentially private information. If
- // the word that this event is a part of is determined to be privacy-sensitive, then this
- // event should not be included in the output log. The system waits to output until the
- // containing word is known.
- final boolean mIsPotentiallyPrivate;
-
- // mIsPotentiallyRevealing indicates that this statement may disclose details about other
- // words typed in other LogUnits. This can happen if the user is not inserting spaces, and
- // data from Suggestions and/or Composing text reveals the entire "megaword". For example,
- // say the user is typing "for the win", and the system wants to record the bigram "the
- // win". If the user types "forthe", omitting the space, the system will give "for the" as
- // a suggestion. If the user accepts the autocorrection, the suggestion for "for the" is
- // included in the log for the word "the", disclosing that the previous word had been "for".
- // For now, we simply do not include this data when logging part of a "megaword".
- final boolean mIsPotentiallyRevealing;
-
- // mKeys stores the names that are the attributes in the output json objects
- final String[] mKeys;
- private static final String[] NULL_KEYS = new String[0];
-
- LogStatement(final String name, final boolean isPotentiallyPrivate,
- final boolean isPotentiallyRevealing, final String... keys) {
- mName = name;
- mIsPotentiallyPrivate = isPotentiallyPrivate;
- mIsPotentiallyRevealing = isPotentiallyRevealing;
- mKeys = (keys == null) ? NULL_KEYS : keys;
- }
- }
-
private static final LogStatement LOGSTATEMENT_FEEDBACK =
- new LogStatement("UserFeedback", false, false, "contents", "accountName");
+ new LogStatement("UserFeedback", false, false, "contents", "accountName", "recording");
public void sendFeedback(final String feedbackContents, final boolean includeHistory,
- final boolean isIncludingAccountName) {
+ final boolean isIncludingAccountName, final boolean isIncludingRecording) {
if (mSavedFeedbackLogBuffer == null) {
return;
}
if (!includeHistory) {
mSavedFeedbackLogBuffer.clear();
}
+ String recording = "";
+ if (isIncludingRecording) {
+ // Try to read recording from recently written json file
+ if (mUserRecordingFile != null) {
+ try {
+ final FileChannel channel =
+ new FileInputStream(mUserRecordingFile).getChannel();
+ final MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0,
+ channel.size());
+ // Android's openFileOutput() creates the file, so we use Android's default
+ // Charset (UTF-8) here to read it.
+ recording = Charset.defaultCharset().decode(buffer).toString();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
final LogUnit feedbackLogUnit = new LogUnit();
final String accountName = isIncludingAccountName ? getAccountName() : "";
feedbackLogUnit.addLogStatement(LOGSTATEMENT_FEEDBACK, SystemClock.uptimeMillis(),
- feedbackContents, accountName);
+ feedbackContents, accountName, recording);
mFeedbackLogBuffer.shiftIn(feedbackLogUnit);
publishLogBuffer(mFeedbackLogBuffer, mSavedFeedbackLog, true /* isIncludingPrivateData */);
mSavedFeedbackLog.close(new Runnable() {
@@ -685,13 +776,25 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
uploadNow();
}
});
+
+ if (isIncludingRecording && DEBUG_REPLAY_AFTER_FEEDBACK) {
+ final Handler handler = new Handler();
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ final ReplayData replayData =
+ mMotionEventReader.readMotionEventData(mUserRecordingFile);
+ mReplayer.replay(replayData);
+ }
+ }, 1000);
+ }
}
public void uploadNow() {
if (DEBUG) {
Log.d(TAG, "calling uploadNow()");
}
- mLatinIME.startService(mUploadIntent);
+ mLatinIME.startService(mUploadNowIntent);
}
public void onLeavingSendFeedbackDialog() {
@@ -734,11 +837,11 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
int height) {
// TODO: Reimplement using a keyboard background image specific to the ResearchLogger
// and remove this method.
- // The check for MainKeyboardView ensures that a red border is only placed around
- // the main keyboard, not every keyboard.
+ // The check for MainKeyboardView ensures that the indicator only decorates the main
+ // keyboard, not every keyboard.
if (IS_SHOWING_INDICATOR && isAllowedToLog() && view instanceof MainKeyboardView) {
final int savedColor = paint.getColor();
- paint.setColor(Color.RED);
+ paint.setColor(isMakingUserRecording() ? Color.YELLOW : Color.RED);
final Style savedStyle = paint.getStyle();
paint.setStyle(Style.STROKE);
final float savedStrokeWidth = paint.getStrokeWidth();
@@ -747,10 +850,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
canvas.drawLine(0, 0, 0, height, paint);
canvas.drawLine(width, 0, width, height, paint);
} else {
- // Put a tiny red dot on the screen so a knowledgeable user can check whether
- // it is enabled. The dot is actually a zero-width, zero-height rectangle,
- // placed at the lower-right corner of the canvas, painted with a non-zero border
- // width.
+ // Put a tiny dot on the screen so a knowledgeable user can check whether it is
+ // enabled. The dot is actually a zero-width, zero-height rectangle, placed at the
+ // lower-right corner of the canvas, painted with a non-zero border width.
paint.setStrokeWidth(3);
canvas.drawRect(width, height, width, height, paint);
}
@@ -770,7 +872,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
private synchronized void enqueueEvent(final LogUnit logUnit, final LogStatement logStatement,
final Object... values) {
- assert values.length == logStatement.mKeys.length;
+ assert values.length == logStatement.getKeys().length;
if (isAllowedToLog() && logUnit != null) {
final long time = SystemClock.uptimeMillis();
logUnit.addLogStatement(logStatement, time, values);
@@ -801,6 +903,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
if (mFeedbackLogBuffer != null) {
mFeedbackLogBuffer.shiftIn(mCurrentLogUnit);
}
+ if (mUserRecordingLogBuffer != null) {
+ mUserRecordingLogBuffer.shiftIn(mCurrentLogUnit);
+ }
mCurrentLogUnit = new LogUnit();
} else {
if (DEBUG) {
@@ -1058,7 +1163,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
*
*/
private static final LogStatement LOGSTATEMENT_MAIN_KEYBOARD_VIEW_PROCESS_MOTION_EVENT =
- new LogStatement("MotionEvent", true, false, "action", "MotionEvent");
+ new LogStatement("MotionEvent", true, false, "action", "MotionEvent", "loggingRelated");
public static void mainKeyboardView_processMotionEvent(final MotionEvent me, final int action,
final long eventTime, final int index, final int id, final int x, final int y) {
if (me != null) {
@@ -1075,12 +1180,16 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
final ResearchLogger researchLogger = getInstance();
researchLogger.enqueueEvent(LOGSTATEMENT_MAIN_KEYBOARD_VIEW_PROCESS_MOTION_EVENT,
- actionString, MotionEvent.obtain(me));
+ actionString, MotionEvent.obtain(me), false);
if (action == MotionEvent.ACTION_DOWN) {
// Subtract 1 from eventTime so the down event is included in the later
// LogUnit, not the earlier (the test is for inequality).
researchLogger.setSavedDownEventTime(eventTime - 1);
}
+ // Refresh the timer in case we are capturing user feedback.
+ if (researchLogger.isMakingUserRecording()) {
+ researchLogger.resetRecordingTimer();
+ }
}
}
@@ -1442,13 +1551,21 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
final int code) {
if (key != null) {
String outputText = key.getOutputText();
- getInstance().enqueueEvent(LOGSTATEMENT_POINTERTRACKER_CALLLISTENERONCODEINPUT,
+ final ResearchLogger researchLogger = getInstance();
+ researchLogger.enqueueEvent(LOGSTATEMENT_POINTERTRACKER_CALLLISTENERONCODEINPUT,
Constants.printableCode(scrubDigitFromCodePoint(code)),
outputText == null ? null : scrubDigitsFromString(outputText.toString()),
x, y, ignoreModifierKey, altersCode, key.isEnabled());
+ if (code == Constants.CODE_RESEARCH) {
+ researchLogger.suppressResearchKeyMotionData();
+ }
}
}
+ private void suppressResearchKeyMotionData() {
+ mCurrentLogUnit.removeResearchButtonInvocation();
+ }
+
/**
* Log a call to PointerTracker.callListenerCallListenerOnRelease().
*