/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.inputmethod.research;

import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
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;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
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;
import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.InputTypeUtils;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.RichInputConnection;
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.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.regex.Pattern;

/**
 * Logs the use of the LatinIME keyboard.
 *
 * This class logs operations on the IME keyboard, including what the user has typed.
 * Data is stored locally in a file in app-specific storage.
 *
 * This functionality is off by default. See
 * {@link ProductionFlag#USES_DEVELOPMENT_ONLY_DIAGNOSTICS}.
 */
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.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
    private static final boolean DEBUG_REPLAY_AFTER_FEEDBACK = false
            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_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
            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
    // Whether the feedback dialog preserves the editable text across invocations.  Should be false
    // for normal research builds so users do not have to delete the same feedback string they
    // entered earlier.  Should be true for builds internal to a development team so when the text
    // field holds a channel name, the developer does not have to re-enter it when using the
    // feedback mechanism to generate multiple tests.
    private static final boolean FEEDBACK_DIALOG_SHOULD_PRESERVE_TEXT_FIELD = false;
    /* package */ static boolean sIsLogging = false;
    private static final int OUTPUT_FORMAT_VERSION = 5;
    private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
    // Whether all words should be recorded, leaving unsampled word between bigrams.  Useful for
    // testing.
    /* package for test */ static final boolean IS_LOGGING_EVERYTHING = false
            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
    // The number of words between n-grams to omit from the log.
    private static final int NUMBER_OF_WORDS_BETWEEN_SAMPLES =
            IS_LOGGING_EVERYTHING ? 0 : (DEBUG ? 2 : 18);

    // Whether to show an indicator on the screen that logging is on.  Currently a very small red
    // dot in the lower right hand corner.  Most users should not notice it.
    private static final boolean IS_SHOWING_INDICATOR = true;
    // Change the default indicator to something very visible.  Currently two red vertical bars on
    // either side of they keyboard.
    private static final boolean IS_SHOWING_INDICATOR_CLEARLY = false ||
            (IS_LOGGING_EVERYTHING && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG);
    // FEEDBACK_WORD_BUFFER_SIZE should add 1 because it must also hold the feedback LogUnit itself.
    public static final int FEEDBACK_WORD_BUFFER_SIZE = (Integer.MAX_VALUE - 1) + 1;

    // constants related to specific log points
    private static final String WHITESPACE_SEPARATORS = " \t\n\r";
    private static final int MAX_INPUTVIEW_LENGTH_TO_CAPTURE = 8192; // must be >=1
    private static final String PREF_RESEARCH_SAVED_CHANNEL = "pref_research_saved_channel";

    private static final long RESEARCHLOG_CLOSE_TIMEOUT_IN_MS = 5 * 1000;
    private static final long RESEARCHLOG_ABORT_TIMEOUT_IN_MS = 5 * 1000;
    private static final long DURATION_BETWEEN_DIR_CLEANUP_IN_MS = DateUtils.DAY_IN_MILLIS;
    private static final long MAX_LOGFILE_AGE_IN_MS = 4 * DateUtils.DAY_IN_MILLIS;

    private static final ResearchLogger sInstance = new ResearchLogger();
    private static String sAccountType = null;
    private static String sAllowedAccountDomain = null;
    /* package */ ResearchLog mMainResearchLog;
    // mFeedbackLog records all events for the session, private or not (excepting
    // passwords).  It is written to permanent storage only if the user explicitly commands
    // the system to do so.
    // LogUnits are queued in the LogBuffers and published to the ResearchLogs when words are
    // complete.
    /* 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;
    private SharedPreferences mPrefs;

    // digits entered by the user are replaced with this codepoint.
    /* package for test */ static final int DIGIT_REPLACEMENT_CODEPOINT =
            Character.codePointAt("\uE000", 0);  // U+E000 is in the "private-use area"
    // U+E001 is in the "private-use area"
    /* package for test */ static final String WORD_REPLACEMENT_STRING = "\uE001";
    protected static final int SUSPEND_DURATION_IN_MINUTES = 1;
    // set when LatinIME should ignore an onUpdateSelection() callback that
    // arises from operations in this class
    private static boolean sLatinIMEExpectingUpdateSelection = false;

    // 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.
    /* package for test */ LatinIME mLatinIME;
    private final Statistics mStatistics;
    private final MotionEventReader mMotionEventReader = new MotionEventReader();
    private final Replayer mReplayer = Replayer.getInstance();
    private ResearchLogDirectory mResearchLogDirectory;

    private Intent mUploadIntent;
    private Intent mUploadNowIntent;

    /* package for test */ LogUnit mCurrentLogUnit = new LogUnit();

    // Gestured or tapped words may be committed after the gesture of the next word has started.
    // To ensure that the gesture data of the next word is not associated with the previous word,
    // 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();
    }

    public static ResearchLogger getInstance() {
        return sInstance;
    }

    public void init(final LatinIME latinIME, final KeyboardSwitcher keyboardSwitcher,
            final Suggest suggest) {
        assert latinIME != null;
        mLatinIME = latinIME;
        mPrefs = PreferenceManager.getDefaultSharedPreferences(latinIME);
        mPrefs.registerOnSharedPreferenceChangeListener(this);

        // Initialize fields from preferences
        sIsLogging = ResearchSettings.readResearchLoggerEnabledFlag(mPrefs);

        // Initialize fields from resources
        final Resources res = latinIME.getResources();
        sAccountType = res.getString(R.string.research_account_type);
        sAllowedAccountDomain = res.getString(R.string.research_allowed_account_domain);

        // Initialize directory manager
        mResearchLogDirectory = new ResearchLogDirectory(mLatinIME);
        cleanLogDirectoryIfNeeded(mResearchLogDirectory, System.currentTimeMillis());

        // Initialize external services
        mUploadIntent = new Intent(mLatinIME, UploaderService.class);
        mUploadNowIntent = new Intent(mLatinIME, UploaderService.class);
        mUploadNowIntent.putExtra(UploaderService.EXTRA_UPLOAD_UNCONDITIONALLY, true);
        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
            UploaderService.cancelAndRescheduleUploadingService(mLatinIME,
                    true /* needsRescheduling */);
        }
        mReplayer.setKeyboardSwitcher(keyboardSwitcher);
    }

    private void cleanLogDirectoryIfNeeded(final ResearchLogDirectory researchLogDirectory,
            final long now) {
        final long lastCleanupTime = ResearchSettings.readResearchLastDirCleanupTime(mPrefs);
        if (now - lastCleanupTime < DURATION_BETWEEN_DIR_CLEANUP_IN_MS) return;
        final long oldestAllowedFileTime = now - MAX_LOGFILE_AGE_IN_MS;
        mResearchLogDirectory.cleanupLogFilesOlderThan(oldestAllowedFileTime);
        ResearchSettings.writeResearchLastDirCleanupTime(mPrefs, now);
    }

    public void mainKeyboardView_onAttachedToWindow(final MainKeyboardView mainKeyboardView) {
        mMainKeyboardView = mainKeyboardView;
        maybeShowSplashScreen();
    }

    public void mainKeyboardView_onDetachedFromWindow() {
        mMainKeyboardView = null;
    }

    public void onDestroy() {
        if (mPrefs != null) {
            mPrefs.unregisterOnSharedPreferenceChangeListener(this);
        }
    }

    private Dialog mSplashDialog = null;

    private void maybeShowSplashScreen() {
        if (ResearchSettings.readHasSeenSplash(mPrefs)) {
            return;
        }
        if (mSplashDialog != null && mSplashDialog.isShowing()) {
            return;
        }
        final IBinder windowToken = mMainKeyboardView != null
                ? mMainKeyboardView.getWindowToken() : null;
        if (windowToken == null) {
            return;
        }
        final AlertDialog.Builder builder = new AlertDialog.Builder(mLatinIME)
                .setTitle(R.string.research_splash_title)
                .setMessage(R.string.research_splash_content)
                .setPositiveButton(android.R.string.yes,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                onUserLoggingConsent();
                                mSplashDialog.dismiss();
                            }
                })
                .setNegativeButton(android.R.string.no,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                final String packageName = mLatinIME.getPackageName();
                                final Uri packageUri = Uri.parse("package:" + packageName);
                                final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE,
                                        packageUri);
                                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                mLatinIME.startActivity(intent);
                            }
                })
                .setCancelable(true)
                .setOnCancelListener(
                        new OnCancelListener() {
                            @Override
                            public void onCancel(DialogInterface dialog) {
                                mLatinIME.requestHideSelf(0);
                            }
                });
        mSplashDialog = builder.create();
        final Window w = mSplashDialog.getWindow();
        final WindowManager.LayoutParams lp = w.getAttributes();
        lp.token = windowToken;
        lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
        w.setAttributes(lp);
        w.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
        mSplashDialog.show();
    }

    public void onUserLoggingConsent() {
        if (mPrefs == null) {
            mPrefs = PreferenceManager.getDefaultSharedPreferences(mLatinIME);
            if (mPrefs == null) return;
        }
        sIsLogging = true;
        ResearchSettings.writeResearchLoggerEnabledFlag(mPrefs, true);
        ResearchSettings.writeHasSeenSplash(mPrefs, true);
        restart();
    }

    private void setLoggingAllowed(final boolean enableLogging) {
        if (mPrefs == null) return;
        sIsLogging = enableLogging;
        ResearchSettings.writeResearchLoggerEnabledFlag(mPrefs, enableLogging);
    }

    private void checkForEmptyEditor() {
        if (mLatinIME == null) {
            return;
        }
        final InputConnection ic = mLatinIME.getCurrentInputConnection();
        if (ic == null) {
            return;
        }
        final CharSequence textBefore = ic.getTextBeforeCursor(1, 0);
        if (!TextUtils.isEmpty(textBefore)) {
            mStatistics.setIsEmptyUponStarting(false);
            return;
        }
        final CharSequence textAfter = ic.getTextAfterCursor(1, 0);
        if (!TextUtils.isEmpty(textAfter)) {
            mStatistics.setIsEmptyUponStarting(false);
            return;
        }
        if (textBefore != null && textAfter != null) {
            mStatistics.setIsEmptyUponStarting(true);
        }
    }

    private void start() {
        if (DEBUG) {
            Log.d(TAG, "start called");
        }
        maybeShowSplashScreen();
        updateSuspendedState();
        requestIndicatorRedraw();
        mStatistics.reset();
        checkForEmptyEditor();
        if (mFeedbackLogBuffer == null) {
            resetFeedbackLogging();
        }
        if (!isAllowedToLog()) {
            // Log.w(TAG, "not in usability mode; not logging");
            return;
        }
        if (mMainLogBuffer == null) {
            mMainResearchLog = new ResearchLog(mResearchLogDirectory.getLogFilePath(
                    System.currentTimeMillis(), System.nanoTime()), mLatinIME);
            final int numWordsToIgnore = new Random().nextInt(NUMBER_OF_WORDS_BETWEEN_SAMPLES + 1);
            mMainLogBuffer = new MainLogBuffer(NUMBER_OF_WORDS_BETWEEN_SAMPLES, numWordsToIgnore,
                    mSuggest) {
                @Override
                protected void publish(final ArrayList<LogUnit> logUnits,
                        boolean canIncludePrivateData) {
                    canIncludePrivateData |= IS_LOGGING_EVERYTHING;
                    for (final LogUnit logUnit : logUnits) {
                        if (DEBUG) {
                            final String wordsString = logUnit.getWordsAsString();
                            Log.d(TAG, "onPublish: '" + wordsString
                                    + "', hc: " + logUnit.containsCorrection()
                                    + ", cipd: " + canIncludePrivateData);
                        }
                        for (final String word : logUnit.getWordsAsStringArray()) {
                            final Dictionary dictionary = getDictionary();
                            mStatistics.recordWordEntered(
                                    dictionary != null && dictionary.isValidWord(word),
                                    logUnit.containsCorrection());
                        }
                    }
                    if (mMainResearchLog != null) {
                        publishLogUnits(logUnits, mMainResearchLog, canIncludePrivateData);
                    }
                }
            };
        }
    }

    private void resetFeedbackLogging() {
        mFeedbackLog = new ResearchLog(mResearchLogDirectory.getLogFilePath(
                System.currentTimeMillis(), System.nanoTime()), mLatinIME);
        mFeedbackLogBuffer = new FixedLogBuffer(FEEDBACK_WORD_BUFFER_SIZE);
    }

    /* package */ void stop() {
        if (DEBUG) {
            Log.d(TAG, "stop called");
        }
        // Commit mCurrentLogUnit before closing.
        commitCurrentLogUnit();

        if (mMainLogBuffer != null) {
            mMainLogBuffer.shiftAndPublishAll();
            logStatistics();
            commitCurrentLogUnit();
            mMainLogBuffer.setIsStopping();
            mMainLogBuffer.shiftAndPublishAll();
            mMainResearchLog.blockingClose(RESEARCHLOG_CLOSE_TIMEOUT_IN_MS);
            mMainLogBuffer = null;
        }
        if (mFeedbackLogBuffer != null) {
            mFeedbackLog.blockingClose(RESEARCHLOG_CLOSE_TIMEOUT_IN_MS);
            mFeedbackLogBuffer = null;
        }
    }

    public void abort() {
        if (DEBUG) {
            Log.d(TAG, "abort called");
        }
        if (mMainLogBuffer != null) {
            mMainLogBuffer.clear();
            mMainResearchLog.blockingAbort(RESEARCHLOG_ABORT_TIMEOUT_IN_MS);
            mMainLogBuffer = null;
        }
        if (mFeedbackLogBuffer != null) {
            mFeedbackLogBuffer.clear();
            mFeedbackLog.blockingAbort(RESEARCHLOG_ABORT_TIMEOUT_IN_MS);
            mFeedbackLogBuffer = null;
        }
    }

    private void restart() {
        stop();
        start();
    }

    private long mResumeTime = 0L;
    private void updateSuspendedState() {
        final long time = System.currentTimeMillis();
        if (time > mResumeTime) {
            mIsLoggingSuspended = false;
        }
    }

    @Override
    public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
        if (key == null || prefs == null) {
            return;
        }
        sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false);
        if (sIsLogging == false) {
            abort();
        }
        requestIndicatorRedraw();
        mPrefs = prefs;
        prefsChanged(prefs);
    }

    public void onResearchKeySelected(final LatinIME latinIME) {
        if (mInFeedbackDialog) {
            Toast.makeText(latinIME, R.string.research_please_exit_feedback_form,
                    Toast.LENGTH_LONG).show();
            return;
        }
        presentFeedbackDialog(latinIME);
    }

    public void presentFeedbackDialog(final LatinIME latinIME) {
        if (isMakingUserRecording()) {
            saveRecording();
        }
        mInFeedbackDialog = true;
        mSavedFeedbackLogBuffer = mFeedbackLogBuffer;
        mSavedFeedbackLog = mFeedbackLog;
        // Set the non-saved versions to null so that the stop() caused by switching to the
        // Feedback dialog will not close them.
        mFeedbackLogBuffer = null;
        mFeedbackLog = null;

        final Intent intent = new Intent();
        intent.setClass(mLatinIME, FeedbackActivity.class);
        if (mFeedbackDialogBundle == null) {
            // Restore feedback field with channel name
            final Bundle bundle = new Bundle();
            bundle.putBoolean(FeedbackFragment.KEY_INCLUDE_ACCOUNT_NAME, true);
            bundle.putBoolean(FeedbackFragment.KEY_HAS_USER_RECORDING, false);
            if (FEEDBACK_DIALOG_SHOULD_PRESERVE_TEXT_FIELD) {
                final String savedChannelName = mPrefs.getString(PREF_RESEARCH_SAVED_CHANNEL, "");
                bundle.putString(FeedbackFragment.KEY_FEEDBACK_STRING, savedChannelName);
            }
            mFeedbackDialogBundle = bundle;
        }
        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() {
        if (mUserRecordingLog != null) {
            mUserRecordingLog.blockingAbort(RESEARCHLOG_ABORT_TIMEOUT_IN_MS);
        }
        mUserRecordingFile = mResearchLogDirectory.getUserRecordingFilePath(
                System.currentTimeMillis(), System.nanoTime());
        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.blockingAbort(RESEARCHLOG_ABORT_TIMEOUT_IN_MS);
        }
        mUserRecordingLog = null;
        mUserRecordingLogBuffer = null;
        if (mFeedbackDialogBundle != null) {
            mFeedbackDialogBundle.putBoolean("HasRecording", false);
        }
    }

    private void saveRecording() {
        commitCurrentLogUnit();
        publishLogBuffer(mUserRecordingLogBuffer, mUserRecordingLog, true);
        mUserRecordingLog.blockingClose(RESEARCHLOG_CLOSE_TIMEOUT_IN_MS);
        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
    // not needed.
    /*
    public void enableOrDisable(final boolean showEnable, final LatinIME latinIME) {
        if (showEnable) {
            if (!sIsLogging) {
                setLoggingAllowed(true);
            }
            resumeLogging();
            Toast.makeText(latinIME,
                    R.string.research_notify_session_logging_enabled,
                    Toast.LENGTH_LONG).show();
        } else {
            Toast toast = Toast.makeText(latinIME,
                    R.string.research_notify_session_log_deleting,
                    Toast.LENGTH_LONG);
            toast.show();
            boolean isLogDeleted = abort();
            final long currentTime = System.currentTimeMillis();
            final long resumeTime = currentTime + 1000 * 60 *
                    SUSPEND_DURATION_IN_MINUTES;
            suspendLoggingUntil(resumeTime);
            toast.cancel();
            Toast.makeText(latinIME, R.string.research_notify_logging_suspended,
                    Toast.LENGTH_LONG).show();
        }
    }
    */

    /**
     * Get the name of the first allowed account on the device.
     *
     * Allowed accounts must be in the domain given by ALLOWED_ACCOUNT_DOMAIN.
     *
     * @return The user's account name.
     */
    public String getAccountName() {
        if (sAccountType == null || sAccountType.isEmpty()) {
            return null;
        }
        if (sAllowedAccountDomain == null || sAllowedAccountDomain.isEmpty()) {
            return null;
        }
        final AccountManager manager = AccountManager.get(mLatinIME);
        // Filter first by account type.
        final Account[] accounts = manager.getAccountsByType(sAccountType);

        for (final Account account : accounts) {
            if (DEBUG) {
                Log.d(TAG, account.name);
            }
            final String[] parts = account.name.split("@");
            if (parts.length > 1 && parts[1].equals(sAllowedAccountDomain)) {
                return parts[0];
            }
        }
        return null;
    }

    private static final LogStatement LOGSTATEMENT_FEEDBACK =
            new LogStatement("UserFeedback", false, false, "contents", "accountName", "recording");
    public void sendFeedback(final String feedbackContents, final boolean includeHistory,
            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) {
                FileChannel channel = null;
                try {
                    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) {
                    Log.e(TAG, "Could not find recording file", e);
                } catch (IOException e) {
                    Log.e(TAG, "Error reading recording file", e);
                } finally {
                    if (channel != null) {
                        try {
                            channel.close();
                        } catch (IOException e) {
                            Log.e(TAG, "Error closing recording file", e);
                        }
                    }
                }
            }
        }
        final LogUnit feedbackLogUnit = new LogUnit();
        final String accountName = isIncludingAccountName ? getAccountName() : "";
        feedbackLogUnit.addLogStatement(LOGSTATEMENT_FEEDBACK, SystemClock.uptimeMillis(),
                feedbackContents, accountName, recording);
        mFeedbackLogBuffer.shiftIn(feedbackLogUnit);
        publishLogBuffer(mFeedbackLogBuffer, mSavedFeedbackLog, true /* isIncludingPrivateData */);
        mSavedFeedbackLog.blockingClose(RESEARCHLOG_CLOSE_TIMEOUT_IN_MS);
        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, null);
                }
            }, 1000);
        }

        if (FEEDBACK_DIALOG_SHOULD_PRESERVE_TEXT_FIELD) {
            // Use feedback string as a channel name to label feedback strings.  Here we record the
            // string for prepopulating the field next time.
            final String channelName = feedbackContents;
            if (mPrefs == null) {
                return;
            }
            mPrefs.edit().putString(PREF_RESEARCH_SAVED_CHANNEL, channelName).apply();
        }
    }

    public void uploadNow() {
        if (DEBUG) {
            Log.d(TAG, "calling uploadNow()");
        }
        mLatinIME.startService(mUploadNowIntent);
    }

    public void onLeavingSendFeedbackDialog() {
        mInFeedbackDialog = false;
    }

    public void initSuggest(final Suggest suggest) {
        mSuggest = suggest;
        // MainLogBuffer has out-of-date Suggest object.  Need to close it down and create a new
        // one.
        if (mMainLogBuffer != null) {
            stop();
            start();
        }
    }

    private Dictionary getDictionary() {
        if (mSuggest == null) {
            return null;
        }
        return mSuggest.getMainDictionary();
    }

    private void setIsPasswordView(boolean isPasswordView) {
        mIsPasswordView = isPasswordView;
    }

    private boolean isAllowedToLog() {
        return !mIsPasswordView && !mIsLoggingSuspended && sIsLogging && !mInFeedbackDialog;
    }

    public void requestIndicatorRedraw() {
        if (!IS_SHOWING_INDICATOR) {
            return;
        }
        if (mMainKeyboardView == null) {
            return;
        }
        mMainKeyboardView.invalidateAllKeys();
    }

    private boolean isReplaying() {
        return mReplayer.isReplaying();
    }

    private int getIndicatorColor() {
        if (isMakingUserRecording()) {
            return Color.YELLOW;
        }
        if (isReplaying()) {
            return Color.GREEN;
        }
        return Color.RED;
    }

    public void paintIndicator(KeyboardView view, Paint paint, Canvas canvas, int width,
            int height) {
        // TODO: Reimplement using a keyboard background image specific to the ResearchLogger
        // and remove this method.
        // The check for MainKeyboardView ensures that the indicator only decorates the main
        // keyboard, not every keyboard.
        if (IS_SHOWING_INDICATOR && (isAllowedToLog() || isReplaying())
                && view instanceof MainKeyboardView) {
            final int savedColor = paint.getColor();
            paint.setColor(getIndicatorColor());
            final Style savedStyle = paint.getStyle();
            paint.setStyle(Style.STROKE);
            final float savedStrokeWidth = paint.getStrokeWidth();
            if (IS_SHOWING_INDICATOR_CLEARLY) {
                paint.setStrokeWidth(5);
                canvas.drawLine(0, 0, 0, height, paint);
                canvas.drawLine(width, 0, width, height, paint);
            } else {
                // 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 - 1, height - 1, width, height, paint);
            }
            paint.setColor(savedColor);
            paint.setStyle(savedStyle);
            paint.setStrokeWidth(savedStrokeWidth);
        }
    }

    /**
     * Buffer a research log event, flagging it as privacy-sensitive.
     */
    private synchronized void enqueueEvent(final LogStatement logStatement,
            final Object... values) {
        enqueueEvent(mCurrentLogUnit, logStatement, values);
    }

    private synchronized void enqueueEvent(final LogUnit logUnit, final LogStatement logStatement,
            final Object... values) {
        assert values.length == logStatement.getKeys().length;
        if (isAllowedToLog() && logUnit != null) {
            final long time = SystemClock.uptimeMillis();
            logUnit.addLogStatement(logStatement, time, values);
        }
    }

    private void setCurrentLogUnitContainsDigitFlag() {
        mCurrentLogUnit.setMayContainDigit();
    }

    private void setCurrentLogUnitContainsCorrection() {
        mCurrentLogUnit.setContainsCorrection();
    }

    private void setCurrentLogUnitCorrectionType(final int correctionType) {
        mCurrentLogUnit.setCorrectionType(correctionType);
    }

    /* package for test */ void commitCurrentLogUnit() {
        if (DEBUG) {
            Log.d(TAG, "commitCurrentLogUnit" + (mCurrentLogUnit.hasOneOrMoreWords() ?
                    ": " + mCurrentLogUnit.getWordsAsString() : ""));
        }
        if (!mCurrentLogUnit.isEmpty()) {
            if (mMainLogBuffer != null) {
                mMainLogBuffer.shiftIn(mCurrentLogUnit);
            }
            if (mFeedbackLogBuffer != null) {
                mFeedbackLogBuffer.shiftIn(mCurrentLogUnit);
            }
            if (mUserRecordingLogBuffer != null) {
                mUserRecordingLogBuffer.shiftIn(mCurrentLogUnit);
            }
            mCurrentLogUnit = new LogUnit();
        } else {
            if (DEBUG) {
                Log.d(TAG, "Warning: tried to commit empty log unit.");
            }
        }
    }

    private static final LogStatement LOGSTATEMENT_UNCOMMIT_CURRENT_LOGUNIT =
            new LogStatement("UncommitCurrentLogUnit", false, false);
    public void uncommitCurrentLogUnit(final String expectedWord,
            final boolean dumpCurrentLogUnit) {
        // The user has deleted this word and returned to the previous.  Check that the word in the
        // logUnit matches the expected word.  If so, restore the last log unit committed to be the
        // current logUnit.  I.e., pull out the last LogUnit from all the LogBuffers, and make
        // restore it to mCurrentLogUnit so the new edits are captured with the word.  Optionally
        // dump the contents of mCurrentLogUnit (useful if they contain deletions of the next word
        // that should not be reported to protect user privacy)
        //
        // Note that we don't use mLastLogUnit here, because it only goes one word back and is only
        // needed for reverts, which only happen one back.
        if (mMainLogBuffer == null) {
            return;
        }
        final LogUnit oldLogUnit = mMainLogBuffer.peekLastLogUnit();

        // Check that expected word matches.
        if (oldLogUnit != null) {
            final String oldLogUnitWords = oldLogUnit.getWordsAsString();
            if (oldLogUnitWords != null && !oldLogUnitWords.equals(expectedWord)) {
                return;
            }
        }

        // Uncommit, merging if necessary.
        mMainLogBuffer.unshiftIn();
        if (oldLogUnit != null && !dumpCurrentLogUnit) {
            oldLogUnit.append(mCurrentLogUnit);
            mSavedDownEventTime = Long.MAX_VALUE;
        }
        if (oldLogUnit == null) {
            mCurrentLogUnit = new LogUnit();
        } else {
            mCurrentLogUnit = oldLogUnit;
        }
        if (mFeedbackLogBuffer != null) {
            mFeedbackLogBuffer.unshiftIn();
        }
        enqueueEvent(LOGSTATEMENT_UNCOMMIT_CURRENT_LOGUNIT);
        if (DEBUG) {
            Log.d(TAG, "uncommitCurrentLogUnit (dump=" + dumpCurrentLogUnit + ") back to "
                    + (mCurrentLogUnit.hasOneOrMoreWords() ? ": '"
                        + mCurrentLogUnit.getWordsAsString() + "'" : ""));
        }
    }

    /**
     * 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 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();
        if (logUnits.isEmpty()) return;
        // LogUnits not containing private data, such as contextual data for the log, do not require
        // logSegment boundary statements.
        if (canIncludePrivateData) {
            openingLogUnit.addLogStatement(LOGSTATEMENT_LOG_SEGMENT_OPENING,
                    SystemClock.uptimeMillis(), canIncludePrivateData);
            researchLog.publish(openingLogUnit, true /* isIncludingPrivateData */);
        }
        for (LogUnit logUnit : logUnits) {
            if (DEBUG) {
                Log.d(TAG, "publishLogBuffer: " + (logUnit.hasOneOrMoreWords()
                        ? logUnit.getWordsAsString() : "<wordless>")
                        + ", correction?: " + logUnit.containsCorrection());
            }
            researchLog.publish(logUnit, canIncludePrivateData);
        }
        if (canIncludePrivateData) {
            final LogUnit closingLogUnit = new LogUnit();
            closingLogUnit.addLogStatement(LOGSTATEMENT_LOG_SEGMENT_CLOSING,
                    SystemClock.uptimeMillis());
            researchLog.publish(closingLogUnit, true /* isIncludingPrivateData */);
        }
    }

    public static boolean hasLetters(final String word) {
        final int length = word.length();
        for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
            final int codePoint = word.codePointAt(i);
            if (Character.isLetter(codePoint)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Commit the portion of mCurrentLogUnit before maxTime as a worded logUnit.
     *
     * After this operation completes, mCurrentLogUnit will hold any logStatements that happened
     * after maxTime.
     */
    /* package for test */ void commitCurrentLogUnitAsWord(final String word, final long maxTime,
            final boolean isBatchMode) {
        if (word == null) {
            return;
        }
        if (word.length() > 0 && hasLetters(word)) {
            mCurrentLogUnit.setWords(word);
        }
        final LogUnit newLogUnit = mCurrentLogUnit.splitByTime(maxTime);
        enqueueCommitText(word, isBatchMode);
        commitCurrentLogUnit();
        mCurrentLogUnit = newLogUnit;
    }

    /**
     * Record the time of a MotionEvent.ACTION_DOWN.
     *
     * Warning: Not thread safe.  Only call from the main thread.
     */
    private void setSavedDownEventTime(final long time) {
        mSavedDownEventTime = time;
    }

    public void onWordFinished(final String word, final boolean isBatchMode) {
        commitCurrentLogUnitAsWord(word, mSavedDownEventTime, isBatchMode);
        mSavedDownEventTime = Long.MAX_VALUE;
    }

    private static int scrubDigitFromCodePoint(int codePoint) {
        return Character.isDigit(codePoint) ? DIGIT_REPLACEMENT_CODEPOINT : codePoint;
    }

    /* package for test */ static String scrubDigitsFromString(String s) {
        StringBuilder sb = null;
        final int length = s.length();
        for (int i = 0; i < length; i = s.offsetByCodePoints(i, 1)) {
            final int codePoint = Character.codePointAt(s, i);
            if (Character.isDigit(codePoint)) {
                if (sb == null) {
                    sb = new StringBuilder(length);
                    sb.append(s.substring(0, i));
                }
                sb.appendCodePoint(DIGIT_REPLACEMENT_CODEPOINT);
            } else {
                if (sb != null) {
                    sb.appendCodePoint(codePoint);
                }
            }
        }
        if (sb == null) {
            return s;
        } else {
            return sb.toString();
        }
    }

    private String scrubWord(String word) {
        final Dictionary dictionary = getDictionary();
        if (dictionary == null) {
            return WORD_REPLACEMENT_STRING;
        }
        if (dictionary.isValidWord(word)) {
            return word;
        }
        return WORD_REPLACEMENT_STRING;
    }

    // Specific logging methods follow below.  The comments for each logging method should
    // indicate what specific method is logged, and how to trigger it from the user interface.
    //
    // Logging methods can be generally classified into two flavors, "UserAction", which should
    // correspond closely to an event that is sensed by the IME, and is usually generated
    // directly by the user, and "SystemResponse" which corresponds to an event that the IME
    // generates, often after much processing of user input.  SystemResponses should correspond
    // closely to user-visible events.
    // TODO: Consider exposing the UserAction classification in the log output.

    /**
     * Log a call to LatinIME.onStartInputViewInternal().
     *
     * UserAction: called each time the keyboard is opened up.
     */
    private static final LogStatement LOGSTATEMENT_LATIN_IME_ON_START_INPUT_VIEW_INTERNAL =
            new LogStatement("LatinImeOnStartInputViewInternal", false, false, "uuid",
                    "packageName", "inputType", "imeOptions", "fieldId", "display", "model",
                    "prefs", "versionCode", "versionName", "outputFormatVersion", "logEverything",
                    "isDevTeamBuild");
    public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo,
            final SharedPreferences prefs) {
        final ResearchLogger researchLogger = getInstance();
        if (editorInfo != null) {
            final boolean isPassword = InputTypeUtils.isPasswordInputType(editorInfo.inputType)
                    || InputTypeUtils.isVisiblePasswordInputType(editorInfo.inputType);
            getInstance().setIsPasswordView(isPassword);
            researchLogger.start();
            final Context context = researchLogger.mLatinIME;
            try {
                final PackageInfo packageInfo;
                packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(),
                        0);
                final Integer versionCode = packageInfo.versionCode;
                final String versionName = packageInfo.versionName;
                final String uuid = ResearchSettings.readResearchLoggerUuid(researchLogger.mPrefs);
                researchLogger.enqueueEvent(LOGSTATEMENT_LATIN_IME_ON_START_INPUT_VIEW_INTERNAL,
                        uuid, editorInfo.packageName, Integer.toHexString(editorInfo.inputType),
                        Integer.toHexString(editorInfo.imeOptions), editorInfo.fieldId,
                        Build.DISPLAY, Build.MODEL, prefs, versionCode, versionName,
                        OUTPUT_FORMAT_VERSION, IS_LOGGING_EVERYTHING,
                        researchLogger.isDevTeamBuild());
                // Commit the logUnit so the LatinImeOnStartInputViewInternal event is in its own
                // logUnit at the beginning of the log.
                researchLogger.commitCurrentLogUnit();
            } catch (final NameNotFoundException e) {
                Log.e(TAG, "NameNotFound", e);
            }
        }
    }

    // TODO: Update this heuristic pattern to something more reliable.  Developer builds tend to
    // have the developer name and year embedded.
    private static final Pattern developerBuildRegex = Pattern.compile("[A-Za-z]\\.20[1-9]");
    private boolean isDevTeamBuild() {
        try {
            final PackageInfo packageInfo;
            packageInfo = mLatinIME.getPackageManager().getPackageInfo(mLatinIME.getPackageName(),
                    0);
            final String versionName = packageInfo.versionName;
            return developerBuildRegex.matcher(versionName).find();
        } catch (final NameNotFoundException e) {
            Log.e(TAG, "Could not determine package name", e);
            return false;
        }
    }

    /**
     * Log a change in preferences.
     *
     * UserAction: called when the user changes the settings.
     */
    private static final LogStatement LOGSTATEMENT_PREFS_CHANGED =
            new LogStatement("PrefsChanged", false, false, "prefs");
    public static void prefsChanged(final SharedPreferences prefs) {
        final ResearchLogger researchLogger = getInstance();
        researchLogger.enqueueEvent(LOGSTATEMENT_PREFS_CHANGED, prefs);
    }

    /**
     * Log a call to MainKeyboardView.processMotionEvent().
     *
     * UserAction: called when the user puts their finger onto the screen (ACTION_DOWN).
     *
     */
    private static final LogStatement LOGSTATEMENT_MAIN_KEYBOARD_VIEW_PROCESS_MOTION_EVENT =
            new LogStatement("MotionEvent", true, false, "action",
                    LogStatement.KEY_IS_LOGGING_RELATED, "motionEvent");
    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) {
            final String actionString = LoggingUtils.getMotionEventActionTypeString(action);
            final ResearchLogger researchLogger = getInstance();
            researchLogger.enqueueEvent(LOGSTATEMENT_MAIN_KEYBOARD_VIEW_PROCESS_MOTION_EVENT,
                    actionString, false /* IS_LOGGING_RELATED */, MotionEvent.obtain(me));
            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();
            }
        }
    }

    /**
     * Log a call to LatinIME.onCodeInput().
     *
     * SystemResponse: The main processing step for entering text.  Called when the user performs a
     * tap, a flick, a long press, releases a gesture, or taps a punctuation suggestion.
     */
    private static final LogStatement LOGSTATEMENT_LATIN_IME_ON_CODE_INPUT =
            new LogStatement("LatinImeOnCodeInput", true, false, "code", "x", "y");
    public static void latinIME_onCodeInput(final int code, final int x, final int y) {
        final long time = SystemClock.uptimeMillis();
        final ResearchLogger researchLogger = getInstance();
        researchLogger.enqueueEvent(LOGSTATEMENT_LATIN_IME_ON_CODE_INPUT,
                Constants.printableCode(scrubDigitFromCodePoint(code)), x, y);
        if (Character.isDigit(code)) {
            researchLogger.setCurrentLogUnitContainsDigitFlag();
        }
        researchLogger.mStatistics.recordChar(code, time);
    }
    /**
     * Log a call to LatinIME.onDisplayCompletions().
     *
     * SystemResponse: The IME has displayed application-specific completions.  They may show up
     * in the suggestion strip, such as a landscape phone.
     */
    private static final LogStatement LOGSTATEMENT_LATINIME_ONDISPLAYCOMPLETIONS =
            new LogStatement("LatinIMEOnDisplayCompletions", true, true,
                    "applicationSpecifiedCompletions");
    public static void latinIME_onDisplayCompletions(
            final CompletionInfo[] applicationSpecifiedCompletions) {
        // Note; passing an array as a single element in a vararg list.  Must create a new
        // dummy array around it or it will get expanded.
        getInstance().enqueueEvent(LOGSTATEMENT_LATINIME_ONDISPLAYCOMPLETIONS,
                new Object[] { applicationSpecifiedCompletions });
    }

    public static boolean getAndClearLatinIMEExpectingUpdateSelection() {
        boolean returnValue = sLatinIMEExpectingUpdateSelection;
        sLatinIMEExpectingUpdateSelection = false;
        return returnValue;
    }

    /**
     * The IME is finishing; it is either being destroyed, or is about to be hidden.
     *
     * UserAction: The user has performed an action that has caused the IME to be closed.  They may
     * have focused on something other than a text field, or explicitly closed it.
     */
    private static final LogStatement LOGSTATEMENT_LATINIME_ONFINISHINPUTVIEWINTERNAL =
            new LogStatement("LatinIMEOnFinishInputViewInternal", false, false, "isTextTruncated",
                    "text");
    public static void latinIME_onFinishInputViewInternal(final boolean finishingInput,
            final int savedSelectionStart, final int savedSelectionEnd, final InputConnection ic) {
        // The finishingInput flag is set in InputMethodService.  It is true if called from
        // doFinishInput(), which can be called as part of doStartInput().  This can happen at times
        // when the IME is not closing, such as when powering up.  The finishinInput flag is false
        // if called from finishViews(), which is called from hideWindow() and onDestroy().  These
        // are the situations in which we want to finish up the researchLog.
        if (ic != null && !finishingInput) {
            final boolean isTextTruncated;
            final String text;
            if (LOG_FULL_TEXTVIEW_CONTENTS) {
                // Capture the TextView contents.  This will trigger onUpdateSelection(), so we
                // set sLatinIMEExpectingUpdateSelection so that when onUpdateSelection() is called,
                // it can tell that it was generated by the logging code, and not by the user, and
                // therefore keep user-visible state as is.
                ic.beginBatchEdit();
                ic.performContextMenuAction(android.R.id.selectAll);
                CharSequence charSequence = ic.getSelectedText(0);
                if (savedSelectionStart != -1 && savedSelectionEnd != -1) {
                    ic.setSelection(savedSelectionStart, savedSelectionEnd);
                }
                ic.endBatchEdit();
                sLatinIMEExpectingUpdateSelection = true;
                if (TextUtils.isEmpty(charSequence)) {
                    isTextTruncated = false;
                    text = "";
                } else {
                    if (charSequence.length() > MAX_INPUTVIEW_LENGTH_TO_CAPTURE) {
                        int length = MAX_INPUTVIEW_LENGTH_TO_CAPTURE;
                        // do not cut in the middle of a supplementary character
                        final char c = charSequence.charAt(length - 1);
                        if (Character.isHighSurrogate(c)) {
                            length--;
                        }
                        final CharSequence truncatedCharSequence = charSequence.subSequence(0,
                                length);
                        isTextTruncated = true;
                        text = truncatedCharSequence.toString();
                    } else {
                        isTextTruncated = false;
                        text = charSequence.toString();
                    }
                }
            } else {
                isTextTruncated = true;
                text = "";
            }
            final ResearchLogger researchLogger = getInstance();
            // Assume that OUTPUT_ENTIRE_BUFFER is only true when we don't care about privacy (e.g.
            // during a live user test), so the normal isPotentiallyPrivate and
            // isPotentiallyRevealing flags do not apply
            researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_ONFINISHINPUTVIEWINTERNAL,
                    isTextTruncated, text);
            researchLogger.commitCurrentLogUnit();
            getInstance().stop();
        }
    }

    /**
     * Log a call to LatinIME.onUpdateSelection().
     *
     * UserAction/SystemResponse: The user has moved the cursor or selection.  This function may
     * be called, however, when the system has moved the cursor, say by inserting a character.
     */
    private static final LogStatement LOGSTATEMENT_LATINIME_ONUPDATESELECTION =
            new LogStatement("LatinIMEOnUpdateSelection", true, false, "lastSelectionStart",
                    "lastSelectionEnd", "oldSelStart", "oldSelEnd", "newSelStart", "newSelEnd",
                    "composingSpanStart", "composingSpanEnd", "expectingUpdateSelection",
                    "expectingUpdateSelectionFromLogger", "context");
    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, final boolean expectingUpdateSelection,
            final boolean expectingUpdateSelectionFromLogger,
            final RichInputConnection connection) {
        String word = "";
        if (connection != null) {
            Range range = connection.getWordRangeAtCursor(WHITESPACE_SEPARATORS, 1);
            if (range != null) {
                word = range.mWord.toString();
            }
        }
        final ResearchLogger researchLogger = getInstance();
        final String scrubbedWord = researchLogger.scrubWord(word);
        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_ONUPDATESELECTION, lastSelectionStart,
                lastSelectionEnd, oldSelStart, oldSelEnd, newSelStart, newSelEnd,
                composingSpanStart, composingSpanEnd, expectingUpdateSelection,
                expectingUpdateSelectionFromLogger, scrubbedWord);
    }

    /**
     * Log a call to LatinIME.onTextInput().
     *
     * SystemResponse: Raw text is added to the TextView.
     */
    public static void latinIME_onTextInput(final String text, final boolean isBatchMode) {
        final ResearchLogger researchLogger = getInstance();
        researchLogger.commitCurrentLogUnitAsWord(text, Long.MAX_VALUE, isBatchMode);
    }

    /**
     * Log a call to LatinIME.pickSuggestionManually().
     *
     * UserAction: The user has chosen a specific word from the suggestion strip.
     */
    private static final LogStatement LOGSTATEMENT_LATINIME_PICKSUGGESTIONMANUALLY =
            new LogStatement("LatinIMEPickSuggestionManually", true, false, "replacedWord", "index",
                    "suggestion", "x", "y", "isBatchMode");
    public static void latinIME_pickSuggestionManually(final String replacedWord,
            final int index, final String suggestion, final boolean isBatchMode) {
        final ResearchLogger researchLogger = getInstance();
        if (!replacedWord.equals(suggestion.toString())) {
            // The user chose something other than what was already there.
            researchLogger.setCurrentLogUnitContainsCorrection();
            researchLogger.setCurrentLogUnitCorrectionType(LogUnit.CORRECTIONTYPE_TYPO);
        }
        final String scrubbedWord = scrubDigitsFromString(suggestion);
        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_PICKSUGGESTIONMANUALLY,
                scrubDigitsFromString(replacedWord), index,
                suggestion == null ? null : scrubbedWord, Constants.SUGGESTION_STRIP_COORDINATE,
                Constants.SUGGESTION_STRIP_COORDINATE, isBatchMode);
        researchLogger.commitCurrentLogUnitAsWord(scrubbedWord, Long.MAX_VALUE, isBatchMode);
        researchLogger.mStatistics.recordManualSuggestion(SystemClock.uptimeMillis());
    }

    /**
     * Log a call to LatinIME.punctuationSuggestion().
     *
     * UserAction: The user has chosen punctuation from the punctuation suggestion strip.
     */
    private static final LogStatement LOGSTATEMENT_LATINIME_PUNCTUATIONSUGGESTION =
            new LogStatement("LatinIMEPunctuationSuggestion", false, false, "index", "suggestion",
                    "x", "y", "isPrediction");
    public static void latinIME_punctuationSuggestion(final int index, final String suggestion,
            final boolean isBatchMode, final boolean isPrediction) {
        final ResearchLogger researchLogger = getInstance();
        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_PUNCTUATIONSUGGESTION, index, suggestion,
                Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE,
                isPrediction);
        researchLogger.commitCurrentLogUnitAsWord(suggestion, Long.MAX_VALUE, isBatchMode);
    }

    /**
     * Log a call to LatinIME.sendKeyCodePoint().
     *
     * SystemResponse: The IME is inserting text into the TextView for numbers, fixed strings, or
     * some other unusual mechanism.
     */
    private static final LogStatement LOGSTATEMENT_LATINIME_SENDKEYCODEPOINT =
            new LogStatement("LatinIMESendKeyCodePoint", true, false, "code");
    public static void latinIME_sendKeyCodePoint(final int code) {
        final ResearchLogger researchLogger = getInstance();
        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_SENDKEYCODEPOINT,
                Constants.printableCode(scrubDigitFromCodePoint(code)));
        if (Character.isDigit(code)) {
            researchLogger.setCurrentLogUnitContainsDigitFlag();
        }
    }

    /**
     * Log a call to LatinIME.promotePhantomSpace().
     *
     * SystemResponse: The IME is inserting a real space in place of a phantom space.
     */
    private static final LogStatement LOGSTATEMENT_LATINIME_PROMOTEPHANTOMSPACE =
            new LogStatement("LatinIMEPromotPhantomSpace", false, false);
    public static void latinIME_promotePhantomSpace() {
        final ResearchLogger researchLogger = getInstance();
        final LogUnit logUnit;
        if (researchLogger.mMainLogBuffer == null) {
            logUnit = researchLogger.mCurrentLogUnit;
        } else {
            logUnit = researchLogger.mMainLogBuffer.peekLastLogUnit();
        }
        researchLogger.enqueueEvent(logUnit, LOGSTATEMENT_LATINIME_PROMOTEPHANTOMSPACE);
    }

    /**
     * Log a call to LatinIME.swapSwapperAndSpace().
     *
     * SystemResponse: A symbol has been swapped with a space character.  E.g. punctuation may swap
     * if a soft space is inserted after a word.
     */
    private static final LogStatement LOGSTATEMENT_LATINIME_SWAPSWAPPERANDSPACE =
            new LogStatement("LatinIMESwapSwapperAndSpace", false, false, "originalCharacters",
                    "charactersAfterSwap");
    public static void latinIME_swapSwapperAndSpace(final CharSequence originalCharacters,
            final String charactersAfterSwap) {
        final ResearchLogger researchLogger = getInstance();
        final LogUnit logUnit;
        if (researchLogger.mMainLogBuffer == null) {
            logUnit = null;
        } else {
            logUnit = researchLogger.mMainLogBuffer.peekLastLogUnit();
        }
        if (logUnit != null) {
            researchLogger.enqueueEvent(logUnit, LOGSTATEMENT_LATINIME_SWAPSWAPPERANDSPACE,
                    originalCharacters, charactersAfterSwap);
        }
    }

    /**
     * Log a call to LatinIME.maybeDoubleSpacePeriod().
     *
     * SystemResponse: Two spaces have been replaced by period space.
     */
    public static void latinIME_maybeDoubleSpacePeriod(final String text,
            final boolean isBatchMode) {
        final ResearchLogger researchLogger = getInstance();
        researchLogger.commitCurrentLogUnitAsWord(text, Long.MAX_VALUE, isBatchMode);
    }

    /**
     * Log a call to MainKeyboardView.onLongPress().
     *
     * UserAction: The user has performed a long-press on a key.
     */
    private static final LogStatement LOGSTATEMENT_MAINKEYBOARDVIEW_ONLONGPRESS =
            new LogStatement("MainKeyboardViewOnLongPress", false, false);
    public static void mainKeyboardView_onLongPress() {
        getInstance().enqueueEvent(LOGSTATEMENT_MAINKEYBOARDVIEW_ONLONGPRESS);
    }

    /**
     * Log a call to MainKeyboardView.setKeyboard().
     *
     * SystemResponse: The IME has switched to a new keyboard (e.g. French, English).
     * This is typically called right after LatinIME.onStartInputViewInternal (when starting a new
     * IME), but may happen at other times if the user explicitly requests a keyboard change.
     */
    private static final LogStatement LOGSTATEMENT_MAINKEYBOARDVIEW_SETKEYBOARD =
            new LogStatement("MainKeyboardViewSetKeyboard", false, false, "elementId", "locale",
                    "orientation", "width", "modeName", "action", "navigateNext",
                    "navigatePrevious", "clobberSettingsKey", "passwordInput", "shortcutKeyEnabled",
                    "hasShortcutKey", "languageSwitchKeyEnabled", "isMultiLine", "tw", "th",
                    "keys");
    public static void mainKeyboardView_setKeyboard(final Keyboard keyboard) {
        final KeyboardId kid = keyboard.mId;
        final boolean isPasswordView = kid.passwordInput();
        final ResearchLogger researchLogger = getInstance();
        researchLogger.setIsPasswordView(isPasswordView);
        researchLogger.enqueueEvent(LOGSTATEMENT_MAINKEYBOARDVIEW_SETKEYBOARD,
                KeyboardId.elementIdToName(kid.mElementId),
                kid.mLocale + ":" + kid.mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
                kid.mOrientation, kid.mWidth, KeyboardId.modeName(kid.mMode), kid.imeAction(),
                kid.navigateNext(), kid.navigatePrevious(), kid.mClobberSettingsKey,
                isPasswordView, kid.mShortcutKeyEnabled, kid.mHasShortcutKey,
                kid.mLanguageSwitchKeyEnabled, kid.isMultiLine(), keyboard.mOccupiedWidth,
                keyboard.mOccupiedHeight, keyboard.mKeys);
    }

    /**
     * Log a call to LatinIME.revertCommit().
     *
     * SystemResponse: The IME has reverted commited text.  This happens when the user enters
     * a word, commits it by pressing space or punctuation, and then reverts the commit by hitting
     * backspace.
     */
    private static final LogStatement LOGSTATEMENT_LATINIME_REVERTCOMMIT =
            new LogStatement("LatinIMERevertCommit", true, false, "committedWord",
                    "originallyTypedWord", "separatorString");
    public static void latinIME_revertCommit(final String committedWord,
            final String originallyTypedWord, final boolean isBatchMode,
            final String separatorString) {
        final ResearchLogger researchLogger = getInstance();
        // TODO: Verify that mCurrentLogUnit has been restored and contains the reverted word.
        final LogUnit logUnit;
        if (researchLogger.mMainLogBuffer == null) {
            logUnit = null;
        } else {
            logUnit = researchLogger.mMainLogBuffer.peekLastLogUnit();
        }
        if (originallyTypedWord.length() > 0 && hasLetters(originallyTypedWord)) {
            if (logUnit != null) {
                logUnit.setWords(originallyTypedWord);
            }
        }
        researchLogger.enqueueEvent(logUnit != null ? logUnit : researchLogger.mCurrentLogUnit,
                LOGSTATEMENT_LATINIME_REVERTCOMMIT, committedWord, originallyTypedWord,
                separatorString);
        if (logUnit != null) {
            logUnit.setContainsCorrection();
        }
        researchLogger.mStatistics.recordRevertCommit(SystemClock.uptimeMillis());
        researchLogger.commitCurrentLogUnitAsWord(originallyTypedWord, Long.MAX_VALUE, isBatchMode);
    }

    /**
     * Log a call to PointerTracker.callListenerOnCancelInput().
     *
     * UserAction: The user has canceled the input, e.g., by pressing down, but then removing
     * outside the keyboard area.
     * TODO: Verify
     */
    private static final LogStatement LOGSTATEMENT_POINTERTRACKER_CALLLISTENERONCANCELINPUT =
            new LogStatement("PointerTrackerCallListenerOnCancelInput", false, false);
    public static void pointerTracker_callListenerOnCancelInput() {
        getInstance().enqueueEvent(LOGSTATEMENT_POINTERTRACKER_CALLLISTENERONCANCELINPUT);
    }

    /**
     * Log a call to PointerTracker.callListenerOnCodeInput().
     *
     * SystemResponse: The user has entered a key through the normal tapping mechanism.
     * LatinIME.onCodeInput will also be called.
     */
    private static final LogStatement LOGSTATEMENT_POINTERTRACKER_CALLLISTENERONCODEINPUT =
            new LogStatement("PointerTrackerCallListenerOnCodeInput", true, false, "code",
                    "outputText", "x", "y", "ignoreModifierKey", "altersCode", "isEnabled");
    public static void pointerTracker_callListenerOnCodeInput(final Key key, final int x,
            final int y, final boolean ignoreModifierKey, final boolean altersCode,
            final int code) {
        if (key != null) {
            String outputText = key.getOutputText();
            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().
     *
     * UserAction: The user has released their finger or thumb from the screen.
     */
    private static final LogStatement LOGSTATEMENT_POINTERTRACKER_CALLLISTENERONRELEASE =
            new LogStatement("PointerTrackerCallListenerOnRelease", true, false, "code",
                    "withSliding", "ignoreModifierKey", "isEnabled");
    public static void pointerTracker_callListenerOnRelease(final Key key, final int primaryCode,
            final boolean withSliding, final boolean ignoreModifierKey) {
        if (key != null) {
            getInstance().enqueueEvent(LOGSTATEMENT_POINTERTRACKER_CALLLISTENERONRELEASE,
                    Constants.printableCode(scrubDigitFromCodePoint(primaryCode)), withSliding,
                    ignoreModifierKey, key.isEnabled());
        }
    }

    /**
     * Log a call to PointerTracker.onDownEvent().
     *
     * UserAction: The user has pressed down on a key.
     * TODO: Differentiate with LatinIME.processMotionEvent.
     */
    private static final LogStatement LOGSTATEMENT_POINTERTRACKER_ONDOWNEVENT =
            new LogStatement("PointerTrackerOnDownEvent", true, false, "deltaT", "distanceSquared");
    public static void pointerTracker_onDownEvent(long deltaT, int distanceSquared) {
        getInstance().enqueueEvent(LOGSTATEMENT_POINTERTRACKER_ONDOWNEVENT, deltaT,
                distanceSquared);
    }

    /**
     * Log a call to PointerTracker.onMoveEvent().
     *
     * UserAction: The user has moved their finger while pressing on the screen.
     * TODO: Differentiate with LatinIME.processMotionEvent().
     */
    private static final LogStatement LOGSTATEMENT_POINTERTRACKER_ONMOVEEVENT =
            new LogStatement("PointerTrackerOnMoveEvent", true, false, "x", "y", "lastX", "lastY");
    public static void pointerTracker_onMoveEvent(final int x, final int y, final int lastX,
            final int lastY) {
        getInstance().enqueueEvent(LOGSTATEMENT_POINTERTRACKER_ONMOVEEVENT, x, y, lastX, lastY);
    }

    /**
     * Log a call to RichInputConnection.commitCompletion().
     *
     * SystemResponse: The IME has committed a completion.  A completion is an application-
     * specific suggestion that is presented in a pop-up menu in the TextView.
     */
    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_COMMITCOMPLETION =
            new LogStatement("RichInputConnectionCommitCompletion", true, false, "completionInfo");
    public static void richInputConnection_commitCompletion(final CompletionInfo completionInfo) {
        final ResearchLogger researchLogger = getInstance();
        researchLogger.enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_COMMITCOMPLETION,
                completionInfo);
    }

    /**
     * Log a call to RichInputConnection.revertDoubleSpacePeriod().
     *
     * SystemResponse: The IME has reverted ". ", which had previously replaced two typed spaces.
     */
    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_REVERTDOUBLESPACEPERIOD =
            new LogStatement("RichInputConnectionRevertDoubleSpacePeriod", false, false);
    public static void richInputConnection_revertDoubleSpacePeriod() {
        getInstance().enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_REVERTDOUBLESPACEPERIOD);
    }

    /**
     * Log a call to RichInputConnection.revertSwapPunctuation().
     *
     * SystemResponse: The IME has reverted a punctuation swap.
     */
    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_REVERTSWAPPUNCTUATION =
            new LogStatement("RichInputConnectionRevertSwapPunctuation", false, false);
    public static void richInputConnection_revertSwapPunctuation() {
        getInstance().enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_REVERTSWAPPUNCTUATION);
    }

    /**
     * Log a call to LatinIME.commitCurrentAutoCorrection().
     *
     * SystemResponse: The IME has committed an auto-correction.  An auto-correction changes the raw
     * text input to another word (or words) that the user more likely desired to type.
     */
    private static final LogStatement LOGSTATEMENT_LATINIME_COMMITCURRENTAUTOCORRECTION =
            new LogStatement("LatinIMECommitCurrentAutoCorrection", true, true, "typedWord",
                    "autoCorrection", "separatorString");
    public static void latinIme_commitCurrentAutoCorrection(final String typedWord,
            final String autoCorrection, final String separatorString, final boolean isBatchMode,
            final SuggestedWords suggestedWords) {
        final String scrubbedTypedWord = scrubDigitsFromString(typedWord);
        final String scrubbedAutoCorrection = scrubDigitsFromString(autoCorrection);
        final ResearchLogger researchLogger = getInstance();
        researchLogger.mCurrentLogUnit.initializeSuggestions(suggestedWords);
        researchLogger.onWordFinished(scrubbedAutoCorrection, isBatchMode);

        // Add the autocorrection logStatement at the end of the logUnit for the committed word.
        // We have to do this after calling commitCurrentLogUnitAsWord, because it may split the
        // current logUnit, and then we have to peek to get the logUnit reference back.
        final LogUnit logUnit = researchLogger.mMainLogBuffer.peekLastLogUnit();
        // TODO: Add test to confirm that the commitCurrentAutoCorrection log statement should
        // always be added to logUnit (if non-null) and not mCurrentLogUnit.
        researchLogger.enqueueEvent(logUnit, LOGSTATEMENT_LATINIME_COMMITCURRENTAUTOCORRECTION,
                scrubbedTypedWord, scrubbedAutoCorrection, separatorString);
    }

    private boolean isExpectingCommitText = false;
    /**
     * Log a call to (UnknownClass).commitPartialText
     *
     * SystemResponse: The IME is committing part of a word.  This happens if a space is
     * automatically inserted to split a single typed string into two or more words.
     */
    // TODO: This method is currently unused.  Find where it should be called from in the IME and
    // add invocations.
    private static final LogStatement LOGSTATEMENT_COMMIT_PARTIAL_TEXT =
            new LogStatement("CommitPartialText", true, false, "newCursorPosition");
    public static void commitPartialText(final String committedWord,
            final long lastTimestampOfWordData, final boolean isBatchMode) {
        final ResearchLogger researchLogger = getInstance();
        final String scrubbedWord = scrubDigitsFromString(committedWord);
        researchLogger.enqueueEvent(LOGSTATEMENT_COMMIT_PARTIAL_TEXT);
        researchLogger.mStatistics.recordAutoCorrection(SystemClock.uptimeMillis());
        researchLogger.commitCurrentLogUnitAsWord(scrubbedWord, lastTimestampOfWordData,
                isBatchMode);
    }

    /**
     * Log a call to RichInputConnection.commitText().
     *
     * SystemResponse: The IME is committing text.  This happens after the user has typed a word
     * and then a space or punctuation key.
     */
    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTIONCOMMITTEXT =
            new LogStatement("RichInputConnectionCommitText", true, false, "newCursorPosition");
    public static void richInputConnection_commitText(final String committedWord,
            final int newCursorPosition, final boolean isBatchMode) {
        final ResearchLogger researchLogger = getInstance();
        // Only include opening and closing logSegments if private data is included
        final String scrubbedWord = scrubDigitsFromString(committedWord);
        if (!researchLogger.isExpectingCommitText) {
            researchLogger.enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTIONCOMMITTEXT,
                    newCursorPosition);
            researchLogger.commitCurrentLogUnitAsWord(scrubbedWord, Long.MAX_VALUE, isBatchMode);
        }
        researchLogger.isExpectingCommitText = false;
    }

    /**
     * Shared event for logging committed text.
     */
    private static final LogStatement LOGSTATEMENT_COMMITTEXT =
            new LogStatement("CommitText", true, false, "committedText", "isBatchMode");
    private void enqueueCommitText(final String word, final boolean isBatchMode) {
        enqueueEvent(LOGSTATEMENT_COMMITTEXT, word, isBatchMode);
    }

    /**
     * Log a call to RichInputConnection.deleteSurroundingText().
     *
     * SystemResponse: The IME has deleted text.
     */
    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_DELETESURROUNDINGTEXT =
            new LogStatement("RichInputConnectionDeleteSurroundingText", true, false,
                    "beforeLength", "afterLength");
    public static void richInputConnection_deleteSurroundingText(final int beforeLength,
            final int afterLength) {
        getInstance().enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_DELETESURROUNDINGTEXT,
                beforeLength, afterLength);
    }

    /**
     * Log a call to RichInputConnection.finishComposingText().
     *
     * SystemResponse: The IME has left the composing text as-is.
     */
    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_FINISHCOMPOSINGTEXT =
            new LogStatement("RichInputConnectionFinishComposingText", false, false);
    public static void richInputConnection_finishComposingText() {
        getInstance().enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_FINISHCOMPOSINGTEXT);
    }

    /**
     * Log a call to RichInputConnection.performEditorAction().
     *
     * SystemResponse: The IME is invoking an action specific to the editor.
     */
    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_PERFORMEDITORACTION =
            new LogStatement("RichInputConnectionPerformEditorAction", false, false,
                    "imeActionId");
    public static void richInputConnection_performEditorAction(final int imeActionId) {
        getInstance().enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_PERFORMEDITORACTION,
                imeActionId);
    }

    /**
     * Log a call to RichInputConnection.sendKeyEvent().
     *
     * SystemResponse: The IME is telling the TextView that a key is being pressed through an
     * alternate channel.
     * TODO: only for hardware keys?
     */
    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_SENDKEYEVENT =
            new LogStatement("RichInputConnectionSendKeyEvent", true, false, "eventTime", "action",
                    "code");
    public static void richInputConnection_sendKeyEvent(final KeyEvent keyEvent) {
        getInstance().enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_SENDKEYEVENT,
                keyEvent.getEventTime(), keyEvent.getAction(), keyEvent.getKeyCode());
    }

    /**
     * Log a call to RichInputConnection.setComposingText().
     *
     * SystemResponse: The IME is setting the composing text.  Happens each time a character is
     * entered.
     */
    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_SETCOMPOSINGTEXT =
            new LogStatement("RichInputConnectionSetComposingText", true, true, "text",
                    "newCursorPosition");
    public static void richInputConnection_setComposingText(final CharSequence text,
            final int newCursorPosition) {
        if (text == null) {
            throw new RuntimeException("setComposingText is null");
        }
        getInstance().enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_SETCOMPOSINGTEXT, text,
                newCursorPosition);
    }

    /**
     * Log a call to RichInputConnection.setSelection().
     *
     * SystemResponse: The IME is requesting that the selection change.  User-initiated selection-
     * change requests do not go through this method -- it's only when the system wants to change
     * the selection.
     */
    private static final LogStatement LOGSTATEMENT_RICHINPUTCONNECTION_SETSELECTION =
            new LogStatement("RichInputConnectionSetSelection", true, false, "from", "to");
    public static void richInputConnection_setSelection(final int from, final int to) {
        getInstance().enqueueEvent(LOGSTATEMENT_RICHINPUTCONNECTION_SETSELECTION, from, to);
    }

    /**
     * Log a call to SuddenJumpingTouchEventHandler.onTouchEvent().
     *
     * SystemResponse: The IME has filtered input events in case of an erroneous sensor reading.
     */
    private static final LogStatement LOGSTATEMENT_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT =
            new LogStatement("SuddenJumpingTouchEventHandlerOnTouchEvent", true, false,
                    "motionEvent");
    public static void suddenJumpingTouchEventHandler_onTouchEvent(final MotionEvent me) {
        if (me != null) {
            getInstance().enqueueEvent(LOGSTATEMENT_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT,
                    me.toString());
        }
    }

    /**
     * Log a call to SuggestionsView.setSuggestions().
     *
     * SystemResponse: The IME is setting the suggestions in the suggestion strip.
     */
    private static final LogStatement LOGSTATEMENT_SUGGESTIONSTRIPVIEW_SETSUGGESTIONS =
            new LogStatement("SuggestionStripViewSetSuggestions", true, true, "suggestedWords");
    public static void suggestionStripView_setSuggestions(final SuggestedWords suggestedWords) {
        if (suggestedWords != null) {
            getInstance().enqueueEvent(LOGSTATEMENT_SUGGESTIONSTRIPVIEW_SETSUGGESTIONS,
                    suggestedWords);
        }
    }

    /**
     * The user has indicated a particular point in the log that is of interest.
     *
     * UserAction: From direct menu invocation.
     */
    private static final LogStatement LOGSTATEMENT_USER_TIMESTAMP =
            new LogStatement("UserTimestamp", false, false);
    public void userTimestamp() {
        getInstance().enqueueEvent(LOGSTATEMENT_USER_TIMESTAMP);
    }

    /**
     * Log a call to LatinIME.onEndBatchInput().
     *
     * SystemResponse: The system has completed a gesture.
     */
    private static final LogStatement LOGSTATEMENT_LATINIME_ONENDBATCHINPUT =
            new LogStatement("LatinIMEOnEndBatchInput", true, false, "enteredText",
                    "enteredWordPos");
    public static void latinIME_onEndBatchInput(final CharSequence enteredText,
            final int enteredWordPos, final SuggestedWords suggestedWords) {
        final ResearchLogger researchLogger = getInstance();
        if (!TextUtils.isEmpty(enteredText) && hasLetters(enteredText.toString())) {
            researchLogger.mCurrentLogUnit.setWords(enteredText.toString());
        }
        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_ONENDBATCHINPUT, enteredText,
                enteredWordPos);
        researchLogger.mCurrentLogUnit.initializeSuggestions(suggestedWords);
        researchLogger.mStatistics.recordGestureInput(enteredText.length(),
                SystemClock.uptimeMillis());
    }

    /**
     * Log a call to LatinIME.handleBackspace() that is not a batch delete.
     *
     * UserInput: The user is deleting one or more characters by hitting the backspace key once.
     * The covers single character deletes as well as deleting selections.
     */
    private static final LogStatement LOGSTATEMENT_LATINIME_HANDLEBACKSPACE =
            new LogStatement("LatinIMEHandleBackspace", true, false, "numCharacters");
    public static void latinIME_handleBackspace(final int numCharacters) {
        final ResearchLogger researchLogger = getInstance();
        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_HANDLEBACKSPACE, numCharacters);
    }

    /**
     * Log a call to LatinIME.handleBackspace() that is a batch delete.
     *
     * UserInput: The user is deleting a gestured word by hitting the backspace key once.
     */
    private static final LogStatement LOGSTATEMENT_LATINIME_HANDLEBACKSPACE_BATCH =
            new LogStatement("LatinIMEHandleBackspaceBatch", true, false, "deletedText",
                    "numCharacters");
    public static void latinIME_handleBackspace_batch(final CharSequence deletedText,
            final int numCharacters) {
        final ResearchLogger researchLogger = getInstance();
        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_HANDLEBACKSPACE_BATCH, deletedText,
                numCharacters);
        researchLogger.mStatistics.recordGestureDelete(deletedText.length(),
                SystemClock.uptimeMillis());
    }

    /**
     * Log a long interval between user operation.
     *
     * UserInput: The user has not done anything for a while.
     */
    private static final LogStatement LOGSTATEMENT_ONUSERPAUSE = new LogStatement("OnUserPause",
            false, false, "intervalInMs");
    public static void onUserPause(final long interval) {
        final ResearchLogger researchLogger = getInstance();
        researchLogger.enqueueEvent(LOGSTATEMENT_ONUSERPAUSE, interval);
    }

    /**
     * Record the current time in case the LogUnit is later split.
     *
     * If the current logUnit is split, then tapping, motion events, etc. before this time should
     * be assigned to one LogUnit, and events after this time should go into the following LogUnit.
     */
    public static void recordTimeForLogUnitSplit() {
        final ResearchLogger researchLogger = getInstance();
        researchLogger.setSavedDownEventTime(SystemClock.uptimeMillis());
        researchLogger.mSavedDownEventTime = Long.MAX_VALUE;
    }

    /**
     * Log a call to LatinIME.handleSeparator()
     *
     * SystemResponse: The system is inserting a separator character, possibly performing auto-
     * correction or other actions appropriate at the end of a word.
     */
    private static final LogStatement LOGSTATEMENT_LATINIME_HANDLESEPARATOR =
            new LogStatement("LatinIMEHandleSeparator", false, false, "primaryCode",
                    "isComposingWord");
    public static void latinIME_handleSeparator(final int primaryCode,
            final boolean isComposingWord) {
        final ResearchLogger researchLogger = getInstance();
        researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_HANDLESEPARATOR, primaryCode,
                isComposingWord);
    }

    /**
     * Log statistics.
     *
     * ContextualData, recorded at the end of a session.
     */
    private static final LogStatement LOGSTATEMENT_STATISTICS =
            new LogStatement("Statistics", false, false, "charCount", "letterCount", "numberCount",
                    "spaceCount", "deleteOpsCount", "wordCount", "isEmptyUponStarting",
                    "isEmptinessStateKnown", "averageTimeBetweenKeys", "averageTimeBeforeDelete",
                    "averageTimeDuringRepeatedDelete", "averageTimeAfterDelete",
                    "dictionaryWordCount", "splitWordsCount", "gestureInputCount",
                    "gestureCharsCount", "gesturesDeletedCount", "manualSuggestionsCount",
                    "revertCommitsCount", "correctedWordsCount", "autoCorrectionsCount");
    private static void logStatistics() {
        final ResearchLogger researchLogger = getInstance();
        final Statistics statistics = researchLogger.mStatistics;
        researchLogger.enqueueEvent(LOGSTATEMENT_STATISTICS, statistics.mCharCount,
                statistics.mLetterCount, statistics.mNumberCount, statistics.mSpaceCount,
                statistics.mDeleteKeyCount, statistics.mWordCount, statistics.mIsEmptyUponStarting,
                statistics.mIsEmptinessStateKnown, statistics.mKeyCounter.getAverageTime(),
                statistics.mBeforeDeleteKeyCounter.getAverageTime(),
                statistics.mDuringRepeatedDeleteKeysCounter.getAverageTime(),
                statistics.mAfterDeleteKeyCounter.getAverageTime(),
                statistics.mDictionaryWordCount, statistics.mSplitWordsCount,
                statistics.mGesturesInputCount, statistics.mGesturesCharsCount,
                statistics.mGesturesDeletedCount, statistics.mManualSuggestionsCount,
                statistics.mRevertCommitsCount, statistics.mCorrectedWordsCount,
                statistics.mAutoCorrectionsCount);
    }
}
