/*
 * 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;
    // 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;
    private ResearchLog mMainResearchLog; // always non-null after init() is called
    // 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 for test */ MainLogBuffer mMainLogBuffer; // always non-null after init() is called
    // 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.
    private ResearchLog mFeedbackLog;
    private LogBuffer mFeedbackLogBuffer;
    /* package */ ResearchLog mUserRecordingLog;
    /* package */ LogBuffer mUserRecordingLogBuffer;
    private File mUserRecordingFile = null;

    private boolean mIsPasswordView = 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 log buffers
        resetLogBuffers();

        // 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 resetLogBuffers() {
        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());
                    }
                }
                publishLogUnits(logUnits, mMainResearchLog, canIncludePrivateData);
            }
        };

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

    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();
        requestIndicatorRedraw();
        mStatistics.reset();
        checkForEmptyEditor();
    }

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

        mMainLogBuffer.shiftAndPublishAll();
        logStatistics();
        commitCurrentLogUnit();
        mMainLogBuffer.setIsStopping();
        mMainLogBuffer.shiftAndPublishAll();
        mMainResearchLog.blockingClose(RESEARCHLOG_CLOSE_TIMEOUT_IN_MS);
        mFeedbackLog.blockingClose(RESEARCHLOG_CLOSE_TIMEOUT_IN_MS);

        resetLogBuffers();
    }

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

        resetLogBuffers();
    }

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

    @Override
    public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
        if (key == null || prefs == null) {
            return;
        }
        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 now has an out-of-date Suggest object.  Close down MainLogBuffer 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 && 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()) {
            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.
        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;
        if (!isAllowedToLog()) 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;
        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;
        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;
        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);
    }
}
