From d05afa3f4c59641c8fabed034e457cb25f0c57f0 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Thu, 22 Mar 2012 11:13:33 +0900 Subject: move usability log code to new class (ResearchLogger) and clean api This change also undoes the effects of I8694eb9016, which was an initial effort built on Utils.UsabilityStudyLogs. Now Utils operates as it did previously, for backward compatibility, but the ResearchLogger retains the new log format. Coordinated with I274b75c5. Bug: 6188932 Change-Id: I41208bdc6b511f69a010c9fc38a936521beba7d5 --- .../android/inputmethod/latin/ResearchLogger.java | 302 +++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 java/src/com/android/inputmethod/latin/ResearchLogger.java (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java new file mode 100644 index 000000000..509fbe0fd --- /dev/null +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -0,0 +1,302 @@ +/* + * 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.latin; + +import android.content.SharedPreferences; +import android.inputmethodservice.InputMethodService; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Process; +import android.text.TextUtils; +import android.util.Log; +import android.view.MotionEvent; + +import com.android.inputmethod.keyboard.Keyboard; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Logs the use of the LatinIME keyboard. + * + * 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. + */ +public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener { + private static final String TAG = ResearchLogger.class.getSimpleName(); + private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; + + private static final ResearchLogger sInstance = new ResearchLogger(new LogFileManager()); + public static boolean sIsLogging = false; + private final Handler mLoggingHandler; + private InputMethodService mIms; + private final Date mDate; + private final SimpleDateFormat mDateFormat; + + /** + * Isolates management of files. This variable should never be null, but can be changed + * to support testing. + */ + private LogFileManager mLogFileManager; + + /** + * Manages the file(s) that stores the logs. + * + * Handles creation, deletion, and provides Readers, Writers, and InputStreams to access + * the logs. + */ + public static class LogFileManager { + private static final String DEFAULT_FILENAME = "log.txt"; + private static final String DEFAULT_LOG_DIRECTORY = "researchLogger"; + + private static final long LOGFILE_PURGE_INTERVAL = 1000 * 60 * 60 * 24; + + private InputMethodService mIms; + private File mFile; + private PrintWriter mPrintWriter; + + /* package */ LogFileManager() { + } + + public void init(InputMethodService ims) { + mIms = ims; + } + + public synchronized void createLogFile() { + try { + createLogFile(DEFAULT_LOG_DIRECTORY, DEFAULT_FILENAME); + } catch (FileNotFoundException e) { + Log.w(TAG, e); + } + } + + public synchronized void createLogFile(String dir, String filename) + throws FileNotFoundException { + if (mIms == null) { + Log.w(TAG, "InputMethodService is not configured. Logging is off."); + return; + } + File filesDir = mIms.getFilesDir(); + if (filesDir == null || !filesDir.exists()) { + Log.w(TAG, "Storage directory does not exist. Logging is off."); + return; + } + File directory = new File(filesDir, dir); + if (!directory.exists()) { + boolean wasCreated = directory.mkdirs(); + if (!wasCreated) { + Log.w(TAG, "Log directory cannot be created. Logging is off."); + return; + } + } + + close(); + mFile = new File(directory, filename); + boolean append = true; + if (mFile.exists() && mFile.lastModified() + LOGFILE_PURGE_INTERVAL < + System.currentTimeMillis()) { + append = false; + } + mPrintWriter = new PrintWriter(new FileOutputStream(mFile, append), true); + } + + public synchronized boolean append(String s) { + if (mPrintWriter == null) { + Log.w(TAG, "PrintWriter is null"); + return false; + } else { + mPrintWriter.print(s); + return !mPrintWriter.checkError(); + } + } + + public synchronized void reset() { + if (mPrintWriter != null) { + mPrintWriter.close(); + mPrintWriter = null; + } + if (mFile != null && mFile.exists()) { + mFile.delete(); + mFile = null; + } + } + + public synchronized void close() { + if (mPrintWriter != null) { + mPrintWriter.close(); + mPrintWriter = null; + mFile = null; + } + } + } + + private ResearchLogger(LogFileManager logFileManager) { + mDate = new Date(); + mDateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss.SSSZ"); + + HandlerThread handlerThread = new HandlerThread("ResearchLogger logging task", + Process.THREAD_PRIORITY_BACKGROUND); + handlerThread.start(); + mLoggingHandler = new Handler(handlerThread.getLooper()); + mLogFileManager = logFileManager; + } + + public static ResearchLogger getInstance() { + return sInstance; + } + + public static void init(InputMethodService ims, SharedPreferences prefs) { + sInstance.initInternal(ims, prefs); + } + + public void initInternal(InputMethodService ims, SharedPreferences prefs) { + mIms = ims; + if (mLogFileManager != null) { + mLogFileManager.init(ims); + mLogFileManager.createLogFile(); + } + if (prefs != null) { + sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); + } + prefs.registerOnSharedPreferenceChangeListener(this); + } + + /** + * Change to a different logFileManager. Will not allow it to be set to null. + */ + /* package */ void setLogFileManager(ResearchLogger.LogFileManager manager) { + if (manager == null) { + Log.w(TAG, "warning: trying to set null logFileManager. ignoring."); + } else { + mLogFileManager = manager; + } + } + + /** + * Represents a category of logging events that share the same subfield structure. + */ + private static enum LogGroup { + MOTION_EVENT("m"), + KEY("k"), + CORRECTION("c"), + STATE_CHANGE("s"); + + private final String mLogString; + + private LogGroup(String logString) { + mLogString = logString; + } + } + + public void logMotionEvent(final int action, final long eventTime, final int id, + final int x, final int y, final float size, final float pressure) { + final String eventTag; + switch (action) { + case MotionEvent.ACTION_CANCEL: eventTag = "[Cancel]"; break; + case MotionEvent.ACTION_UP: eventTag = "[Up]"; break; + case MotionEvent.ACTION_DOWN: eventTag = "[Down]"; break; + case MotionEvent.ACTION_POINTER_UP: eventTag = "[PointerUp]"; break; + case MotionEvent.ACTION_POINTER_DOWN: eventTag = "[PointerDown]"; break; + case MotionEvent.ACTION_MOVE: eventTag = "[Move]"; break; + case MotionEvent.ACTION_OUTSIDE: eventTag = "[Outside]"; break; + default: eventTag = "[Action" + action + "]"; break; + } + if (!TextUtils.isEmpty(eventTag)) { + StringBuilder sb = new StringBuilder(); + sb.append(eventTag); + sb.append('\t'); sb.append(eventTime); + sb.append('\t'); sb.append(id); + sb.append('\t'); sb.append(x); + sb.append('\t'); sb.append(y); + sb.append('\t'); sb.append(size); + sb.append('\t'); sb.append(pressure); + write(LogGroup.MOTION_EVENT, sb.toString()); + } + } + + public void logKeyEvent(int code, int x, int y) { + final StringBuilder sb = new StringBuilder(); + sb.append(Keyboard.printableCode(code)); + sb.append('\t'); sb.append(x); + sb.append('\t'); sb.append(y); + write(LogGroup.KEY, sb.toString()); + + LatinImeLogger.onPrintAllUsabilityStudyLogs(); + } + + public void logCorrection(String subgroup, String before, String after, int position) { + final StringBuilder sb = new StringBuilder(); + sb.append(subgroup); + sb.append('\t'); sb.append(before); + sb.append('\t'); sb.append(after); + sb.append('\t'); sb.append(position); + write(LogGroup.CORRECTION, sb.toString()); + } + + public void logStateChange(String subgroup, String details) { + write(LogGroup.STATE_CHANGE, subgroup + "\t" + details); + } + + private void write(final LogGroup logGroup, final String log) { + mLoggingHandler.post(new Runnable() { + @Override + public void run() { + final long currentTime = System.currentTimeMillis(); + mDate.setTime(currentTime); + + final String printString = String.format("%s\t%d\t%s\t%s\n", + mDateFormat.format(mDate), currentTime, logGroup.mLogString, log); + if (LatinImeLogger.sDBG) { + Log.d(TAG, "Write: " + '[' + logGroup.mLogString + ']' + log); + } + if (mLogFileManager.append(printString)) { + // success + } else { + if (LatinImeLogger.sDBG) { + Log.w(TAG, "Unable to write to log."); + } + } + } + }); + } + + public void clearAll() { + mLoggingHandler.post(new Runnable() { + @Override + public void run() { + if (LatinImeLogger.sDBG) { + Log.d(TAG, "Delete log file."); + } + mLogFileManager.reset(); + } + }); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { + if (key == null || prefs == null) { + return; + } + sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); + } +} -- cgit v1.2.3-83-g751a From 2482e6c386f2bd6bffa336a95229caf53508b3b2 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Fri, 23 Mar 2012 22:00:15 +0900 Subject: add tests for ResearchLogger Bug: 6188932 Change-Id: Icf407f9d145d2b25b70d5d7bc30ee3d64561620c --- java/proguard.flags | 4 + .../android/inputmethod/latin/ResearchLogger.java | 16 ++- .../inputmethod/latin/ResearchLoggerTests.java | 156 +++++++++++++++++++++ 3 files changed, 169 insertions(+), 7 deletions(-) create mode 100644 tests/src/com/android/inputmethod/latin/ResearchLoggerTests.java (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/proguard.flags b/java/proguard.flags index 701786a84..e33706c47 100644 --- a/java/proguard.flags +++ b/java/proguard.flags @@ -47,6 +47,10 @@ (...); } +-keep class com.android.inputmethod.latin.ResearchLogger { + void setLogFileManager(...); +} + # The support library contains references to newer platform versions. # Don't warn about those in case this app is linking against an older # platform version. We know about them, and they are safe. diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 509fbe0fd..3b110bd78 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -21,6 +21,7 @@ import android.inputmethodservice.InputMethodService; import android.os.Handler; import android.os.HandlerThread; import android.os.Process; +import android.os.SystemClock; import android.text.TextUtils; import android.util.Log; import android.view.MotionEvent; @@ -48,7 +49,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final ResearchLogger sInstance = new ResearchLogger(new LogFileManager()); public static boolean sIsLogging = false; - private final Handler mLoggingHandler; + /* package */ final Handler mLoggingHandler; private InputMethodService mIms; private final Date mDate; private final SimpleDateFormat mDateFormat; @@ -182,11 +183,13 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } /** - * Change to a different logFileManager. Will not allow it to be set to null. + * Change to a different logFileManager. + * + * @throws IllegalArgumentException if logFileManager is null */ - /* package */ void setLogFileManager(ResearchLogger.LogFileManager manager) { + void setLogFileManager(LogFileManager manager) { if (manager == null) { - Log.w(TAG, "warning: trying to set null logFileManager. ignoring."); + throw new IllegalArgumentException("warning: trying to set null logFileManager"); } else { mLogFileManager = manager; } @@ -240,8 +243,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang sb.append('\t'); sb.append(x); sb.append('\t'); sb.append(y); write(LogGroup.KEY, sb.toString()); - - LatinImeLogger.onPrintAllUsabilityStudyLogs(); } public void logCorrection(String subgroup, String before, String after, int position) { @@ -263,9 +264,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang public void run() { final long currentTime = System.currentTimeMillis(); mDate.setTime(currentTime); + final long upTime = SystemClock.uptimeMillis(); final String printString = String.format("%s\t%d\t%s\t%s\n", - mDateFormat.format(mDate), currentTime, logGroup.mLogString, log); + mDateFormat.format(mDate), upTime, logGroup.mLogString, log); if (LatinImeLogger.sDBG) { Log.d(TAG, "Write: " + '[' + logGroup.mLogString + ']' + log); } diff --git a/tests/src/com/android/inputmethod/latin/ResearchLoggerTests.java b/tests/src/com/android/inputmethod/latin/ResearchLoggerTests.java new file mode 100644 index 000000000..6ccc4f22b --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/ResearchLoggerTests.java @@ -0,0 +1,156 @@ +/* + * 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.latin; + +import android.inputmethodservice.InputMethodService; +import android.os.Handler; +import android.util.Log; +import android.view.MotionEvent; + +import com.android.inputmethod.latin.ResearchLogger.LogFileManager; + +import java.io.FileNotFoundException; + +public class ResearchLoggerTests extends InputTestsBase { + + private static final String TAG = ResearchLoggerTests.class.getSimpleName(); + private static final int TEST_INT = 0x12345678; + private static final long TEST_LONG = 0x1234567812345678L; + + private static ResearchLogger sLogger; + private MockLogFileManager mMockLogFileManager; + + @Override + protected void setUp() { + super.setUp(); + sLogger = ResearchLogger.getInstance(); + mMockLogFileManager = new MockLogFileManager(); + sLogger.setLogFileManager(mMockLogFileManager); + ResearchLogger.sIsLogging = true; + } + + public static class MockLogFileManager extends LogFileManager { + private final StringBuilder mContents = new StringBuilder(); + + @Override + public void init(InputMethodService ims) { + } + + @Override + public synchronized void createLogFile() { + mContents.setLength(0); + } + + @Override + public synchronized void createLogFile(String dir, String filename) + throws FileNotFoundException { + mContents.setLength(0); + } + + @Override + public synchronized boolean append(String s) { + mContents.append(s); + return true; + } + + @Override + public synchronized void reset() { + mContents.setLength(0); + } + + @Override + public synchronized void close() { + mContents.setLength(0); + } + + private String getAppendedString() { + return mContents.toString(); + } + } + + private void waitOnResearchLogger() { + // post another Runnable that notify()'s the test that it may proceed. + // assumes that the MessageQueue is processed in-order + Handler handler = sLogger.mLoggingHandler; + handler.post(new Runnable() { + @Override + public void run() { + synchronized (ResearchLoggerTests.this) { + ResearchLoggerTests.this.notify(); + } + } + }); + synchronized (this) { + try { + wait(); + } catch (InterruptedException e) { + Log.i(TAG, "interrupted when waiting for handler to finish.", e); + } + } + } + + /*********************** Tests *********************/ + public void testLogStartsEmpty() { + waitOnResearchLogger(); + String result = mMockLogFileManager.getAppendedString(); + assertEquals(result, ""); + } + + public void testMotionEvent() { + // verify that input values appear somewhere in output + sLogger.logMotionEvent(MotionEvent.ACTION_CANCEL, + TEST_LONG, TEST_INT, 1111, 3333, 5555, 7777); + waitOnResearchLogger(); + String output = mMockLogFileManager.getAppendedString(); + assertTrue(output.matches("(?sui).*\\bcancel\\b.*")); + assertFalse(output.matches("(?sui).*\\bdown\\b.*")); + assertTrue(output.matches("(?s).*\\b" + TEST_LONG + "\\b.*")); + assertTrue(output.matches("(?s).*\\b" + TEST_INT + "\\b.*")); + assertTrue(output.matches("(?s).*\\b1111\\b.*")); + assertTrue(output.matches("(?s).*\\b3333\\b.*")); + assertTrue(output.matches("(?s).*\\b5555\\b.*")); + assertTrue(output.matches("(?s).*\\b7777\\b.*")); + } + + public void testKeyEvent() { + type("abc"); + waitOnResearchLogger(); + String output = mMockLogFileManager.getAppendedString(); + assertTrue(output.matches("(?s).*\\ba\\b.*")); + assertTrue(output.matches("(?s).*\\bb\\b.*")); + assertTrue(output.matches("(?s).*\\bc\\b.*")); + } + + public void testCorrection() { + sLogger.logCorrection("aaaa", "thos", "this", 1); + waitOnResearchLogger(); + String output = mMockLogFileManager.getAppendedString(); + assertTrue(output.matches("(?sui).*\\baaaa\\b.*")); + assertTrue(output.matches("(?sui).*\\bthos\\b.*")); + assertTrue(output.matches("(?sui).*\\bthis\\b.*")); + } + + public void testStateChange() { + sLogger.logStateChange("aaaa", "bbbb"); + waitOnResearchLogger(); + String output = mMockLogFileManager.getAppendedString(); + assertTrue(output.matches("(?sui).*\\baaaa\\b.*")); + assertTrue(output.matches("(?sui).*\\bbbbb\\b.*")); + } + + // TODO: add integration tests that start at point of event generation. +} -- cgit v1.2.3-83-g751a From c166697e3f5ec600089987dbbff0be7f3e308565 Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Mon, 26 Mar 2012 22:10:21 +0900 Subject: Optimization: Start making use of ProductionFlag.IS_EXPERIMENTAL for ResearchLogger Move GodMode specific tests to relevant directories as well. This goes along with I9dc4d469 Change-Id: I4a21c53846b26eede346cb1da13e6abbdf9ec27f --- .../inputmethod/keyboard/LatinKeyboardView.java | 35 +++-- .../com/android/inputmethod/latin/LatinIME.java | 11 +- .../android/inputmethod/latin/LatinImeLogger.java | 4 - .../android/inputmethod/latin/ResearchLogger.java | 2 +- .../com/android/inputmethod/latin/Settings.java | 6 +- .../inputmethod/latin/ResearchLoggerTests.java | 156 --------------------- 6 files changed, 32 insertions(+), 182 deletions(-) delete mode 100644 tests/src/com/android/inputmethod/latin/ResearchLoggerTests.java (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 3f6c37477..7194cced3 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -52,6 +52,7 @@ import com.android.inputmethod.latin.StringUtils; import com.android.inputmethod.latin.SubtypeUtils; import com.android.inputmethod.latin.Utils; import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils; +import com.android.inputmethod.latin.define.ProductionFlag; import java.util.Locale; import java.util.WeakHashMap; @@ -694,15 +695,17 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke + size + "," + pressure); } } - if (ResearchLogger.sIsLogging) { - // TODO: remove redundant calculations of size and pressure by - // removing UsabilityStudyLog code once the ResearchLogger is mature enough - final float size = me.getSize(index); - final float pressure = me.getPressure(index); - if (action != MotionEvent.ACTION_MOVE) { - // Skip ACTION_MOVE events as they are logged below - ResearchLogger.getInstance().logMotionEvent(action, eventTime, id, x, - y, size, pressure); + if (ProductionFlag.IS_EXPERIMENTAL) { + if (ResearchLogger.sIsLogging) { + // TODO: remove redundant calculations of size and pressure by + // removing UsabilityStudyLog code once the ResearchLogger is mature enough + final float size = me.getSize(index); + final float pressure = me.getPressure(index); + if (action != MotionEvent.ACTION_MOVE) { + // Skip ACTION_MOVE events as they are logged below + ResearchLogger.getInstance().logMotionEvent(action, eventTime, id, x, y, + size, pressure); + } } } @@ -770,12 +773,14 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke + pointerId + "," + px + "," + py + "," + pointerSize + "," + pointerPressure); } - if (ResearchLogger.sIsLogging) { - // TODO: earlier comment about redundant calculations applies here too - final float pointerSize = me.getSize(i); - final float pointerPressure = me.getPressure(i); - ResearchLogger.getInstance().logMotionEvent(action, eventTime, pointerId, - px, py, pointerSize, pointerPressure); + if (ProductionFlag.IS_EXPERIMENTAL) { + if (ResearchLogger.sIsLogging) { + // TODO: earlier comment about redundant calculations applies here too + final float pointerSize = me.getSize(i); + final float pointerPressure = me.getPressure(i); + ResearchLogger.getInstance().logMotionEvent(action, eventTime, pointerId, + px, py, pointerSize, pointerPressure); + } } } } else { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 7272006a2..0669ee668 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -69,6 +69,7 @@ import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardView; import com.android.inputmethod.keyboard.LatinKeyboardView; import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils; +import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.latin.suggestions.SuggestionsView; import java.io.FileDescriptor; @@ -439,7 +440,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); mPrefs = prefs; LatinImeLogger.init(this, prefs); - ResearchLogger.init(this, prefs); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.init(this, prefs); + } LanguageSwitcherProxy.init(this, prefs); InputMethodManagerCompatWrapper.init(this); SubtypeSwitcher.init(this); @@ -1264,8 +1267,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } mLastKeyTime = when; - if (ResearchLogger.sIsLogging) { - ResearchLogger.getInstance().logKeyEvent(primaryCode, x, y); + if (ProductionFlag.IS_EXPERIMENTAL) { + if (ResearchLogger.sIsLogging) { + ResearchLogger.getInstance().logKeyEvent(primaryCode, x, y); + } } final KeyboardSwitcher switcher = mKeyboardSwitcher; diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java index 079f3b5dd..732efadd6 100644 --- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java +++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java @@ -80,8 +80,4 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang public static void onPrintAllUsabilityStudyLogs() { } - - public static boolean isResearcherPackage(Context context) { - return false; - } } diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 3b110bd78..0694ffe77 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -41,7 +41,7 @@ import java.util.Date; * 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. + * This functionality is off by default. See {@link ProductionFlag.IS_EXPERIMENTAL}. */ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = ResearchLogger.class.getSimpleName(); diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 72391f31e..110264892 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -46,6 +46,7 @@ import com.android.inputmethod.compat.CompatUtils; import com.android.inputmethod.compat.InputMethodServiceCompatWrapper; import com.android.inputmethod.compat.VibratorCompatWrapper; import com.android.inputmethod.deprecated.VoiceProxy; +import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethodcommon.InputMethodSettingsActivity; import java.util.Locale; @@ -238,17 +239,16 @@ public class Settings extends InputMethodSettingsActivity textCorrectionGroup.removePreference(dictionaryLink); } - final boolean isResearcherPackage = LatinImeLogger.isResearcherPackage(this); final boolean showUsabilityStudyModeOption = res.getBoolean(R.bool.config_enable_usability_study_mode_option) - || isResearcherPackage || ENABLE_EXPERIMENTAL_SETTINGS; + || ProductionFlag.IS_EXPERIMENTAL || ENABLE_EXPERIMENTAL_SETTINGS; final Preference usabilityStudyPref = findPreference(PREF_USABILITY_STUDY_MODE); if (!showUsabilityStudyModeOption) { if (usabilityStudyPref != null) { miscSettings.removePreference(usabilityStudyPref); } } - if (isResearcherPackage) { + if (ProductionFlag.IS_EXPERIMENTAL) { if (usabilityStudyPref instanceof CheckBoxPreference) { CheckBoxPreference checkbox = (CheckBoxPreference)usabilityStudyPref; checkbox.setChecked(prefs.getBoolean(PREF_USABILITY_STUDY_MODE, true)); diff --git a/tests/src/com/android/inputmethod/latin/ResearchLoggerTests.java b/tests/src/com/android/inputmethod/latin/ResearchLoggerTests.java deleted file mode 100644 index 6ccc4f22b..000000000 --- a/tests/src/com/android/inputmethod/latin/ResearchLoggerTests.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * 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.latin; - -import android.inputmethodservice.InputMethodService; -import android.os.Handler; -import android.util.Log; -import android.view.MotionEvent; - -import com.android.inputmethod.latin.ResearchLogger.LogFileManager; - -import java.io.FileNotFoundException; - -public class ResearchLoggerTests extends InputTestsBase { - - private static final String TAG = ResearchLoggerTests.class.getSimpleName(); - private static final int TEST_INT = 0x12345678; - private static final long TEST_LONG = 0x1234567812345678L; - - private static ResearchLogger sLogger; - private MockLogFileManager mMockLogFileManager; - - @Override - protected void setUp() { - super.setUp(); - sLogger = ResearchLogger.getInstance(); - mMockLogFileManager = new MockLogFileManager(); - sLogger.setLogFileManager(mMockLogFileManager); - ResearchLogger.sIsLogging = true; - } - - public static class MockLogFileManager extends LogFileManager { - private final StringBuilder mContents = new StringBuilder(); - - @Override - public void init(InputMethodService ims) { - } - - @Override - public synchronized void createLogFile() { - mContents.setLength(0); - } - - @Override - public synchronized void createLogFile(String dir, String filename) - throws FileNotFoundException { - mContents.setLength(0); - } - - @Override - public synchronized boolean append(String s) { - mContents.append(s); - return true; - } - - @Override - public synchronized void reset() { - mContents.setLength(0); - } - - @Override - public synchronized void close() { - mContents.setLength(0); - } - - private String getAppendedString() { - return mContents.toString(); - } - } - - private void waitOnResearchLogger() { - // post another Runnable that notify()'s the test that it may proceed. - // assumes that the MessageQueue is processed in-order - Handler handler = sLogger.mLoggingHandler; - handler.post(new Runnable() { - @Override - public void run() { - synchronized (ResearchLoggerTests.this) { - ResearchLoggerTests.this.notify(); - } - } - }); - synchronized (this) { - try { - wait(); - } catch (InterruptedException e) { - Log.i(TAG, "interrupted when waiting for handler to finish.", e); - } - } - } - - /*********************** Tests *********************/ - public void testLogStartsEmpty() { - waitOnResearchLogger(); - String result = mMockLogFileManager.getAppendedString(); - assertEquals(result, ""); - } - - public void testMotionEvent() { - // verify that input values appear somewhere in output - sLogger.logMotionEvent(MotionEvent.ACTION_CANCEL, - TEST_LONG, TEST_INT, 1111, 3333, 5555, 7777); - waitOnResearchLogger(); - String output = mMockLogFileManager.getAppendedString(); - assertTrue(output.matches("(?sui).*\\bcancel\\b.*")); - assertFalse(output.matches("(?sui).*\\bdown\\b.*")); - assertTrue(output.matches("(?s).*\\b" + TEST_LONG + "\\b.*")); - assertTrue(output.matches("(?s).*\\b" + TEST_INT + "\\b.*")); - assertTrue(output.matches("(?s).*\\b1111\\b.*")); - assertTrue(output.matches("(?s).*\\b3333\\b.*")); - assertTrue(output.matches("(?s).*\\b5555\\b.*")); - assertTrue(output.matches("(?s).*\\b7777\\b.*")); - } - - public void testKeyEvent() { - type("abc"); - waitOnResearchLogger(); - String output = mMockLogFileManager.getAppendedString(); - assertTrue(output.matches("(?s).*\\ba\\b.*")); - assertTrue(output.matches("(?s).*\\bb\\b.*")); - assertTrue(output.matches("(?s).*\\bc\\b.*")); - } - - public void testCorrection() { - sLogger.logCorrection("aaaa", "thos", "this", 1); - waitOnResearchLogger(); - String output = mMockLogFileManager.getAppendedString(); - assertTrue(output.matches("(?sui).*\\baaaa\\b.*")); - assertTrue(output.matches("(?sui).*\\bthos\\b.*")); - assertTrue(output.matches("(?sui).*\\bthis\\b.*")); - } - - public void testStateChange() { - sLogger.logStateChange("aaaa", "bbbb"); - waitOnResearchLogger(); - String output = mMockLogFileManager.getAppendedString(); - assertTrue(output.matches("(?sui).*\\baaaa\\b.*")); - assertTrue(output.matches("(?sui).*\\bbbbb\\b.*")); - } - - // TODO: add integration tests that start at point of event generation. -} -- cgit v1.2.3-83-g751a From 2d9483ff16a6471aaa36c34fb6c3d043e4327abc Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Wed, 28 Mar 2012 17:36:05 -0700 Subject: make ResearchLogger log write only Bug: 6188932 Change-Id: I8a8f944b1d4ee858d5ecaad0d3adc6dc7af54f68 --- java/src/com/android/inputmethod/latin/ResearchLogger.java | 1 + 1 file changed, 1 insertion(+) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 0694ffe77..f39f082bc 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -113,6 +113,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang close(); mFile = new File(directory, filename); + mFile.setReadable(false, false); boolean append = true; if (mFile.exists() && mFile.lastModified() + LOGFILE_PURGE_INTERVAL < System.currentTimeMillis()) { -- cgit v1.2.3-83-g751a From c61cd79229b1871d0f603a23389695d7f7751e66 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 29 Mar 2012 15:07:53 +0900 Subject: Fix some obvious compiler warnings Change-Id: I10a634f7492b45d5a72345f14d36cf341946387d --- .../inputmethod/compat/InputMethodManagerCompatWrapper.java | 9 +++++---- .../com/android/inputmethod/compat/SuggestionSpanUtils.java | 2 +- .../inputmethod/compat/SuggestionsInfoCompatUtils.java | 4 ++-- .../android/inputmethod/keyboard/KeyboardActionListener.java | 12 ++++++------ .../inputmethod/latin/BinaryDictionaryFileDumper.java | 2 +- java/src/com/android/inputmethod/latin/Dictionary.java | 2 +- java/src/com/android/inputmethod/latin/LatinIME.java | 1 - java/src/com/android/inputmethod/latin/LatinImeLogger.java | 1 - java/src/com/android/inputmethod/latin/ResearchLogger.java | 2 +- java/src/com/android/inputmethod/latin/WordComposer.java | 4 +--- 10 files changed, 18 insertions(+), 21 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java index bf5f20158..a4ff8238c 100644 --- a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java @@ -267,12 +267,13 @@ public class InputMethodManagerCompatWrapper { final InputMethodSubtypeCompatWrapper currentIms = getCurrentInputMethodSubtype(); final List imiList = getEnabledInputMethodList(); imiList.remove(myImi); + final PackageManager pm = mPackageManager; Collections.sort(imiList, new Comparator() { @Override public int compare(InputMethodInfoCompatWrapper imi1, InputMethodInfoCompatWrapper imi2) { - final CharSequence imiId1 = imi1.loadLabel(mPackageManager) + "/" + imi1.getId(); - final CharSequence imiId2 = imi2.loadLabel(mPackageManager) + "/" + imi2.getId(); + final CharSequence imiId1 = imi1.loadLabel(pm) + "/" + imi1.getId(); + final CharSequence imiId2 = imi2.loadLabel(pm) + "/" + imi2.getId(); return imiId1.toString().compareTo(imiId2.toString()); } }); @@ -302,6 +303,7 @@ public class InputMethodManagerCompatWrapper { index++; } + final InputMethodServiceCompatWrapper service = mService; final OnClickListener buttonListener = new OnClickListener() { @Override public void onClick(DialogInterface di, int whichButton) { @@ -309,10 +311,9 @@ public class InputMethodManagerCompatWrapper { intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_CLEAR_TOP); - mService.startActivity(intent); + service.startActivity(intent); } }; - final InputMethodServiceCompatWrapper service = mService; final IBinder token = service.getWindow().getWindow().getAttributes().token; final OnClickListener selectionListener = new OnClickListener() { @Override diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java index a9e48404a..df55aee94 100644 --- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java +++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java @@ -129,7 +129,7 @@ public class SuggestionSpanUtils { // TODO: Share the implementation for checking typed word validity between the IME // and the spell checker. final int flag = (sameAsTyped && !suggestedWords.mTypedWordValid) - ? ((int)OBJ_FLAG_EASY_CORRECT | (int)OBJ_FLAG_MISSPELLED) + ? (OBJ_FLAG_EASY_CORRECT | OBJ_FLAG_MISSPELLED) : 0; final Object[] args = diff --git a/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java b/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java index 6a0d4dd9e..723ec2862 100644 --- a/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java @@ -24,7 +24,7 @@ public class SuggestionsInfoCompatUtils { private static final Field FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = CompatUtils.getField( SuggestionsInfo.class, "RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS"); private static final Integer OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = (Integer) CompatUtils - .getFieldValue(null, null, FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS);; + .getFieldValue(null, null, FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS); private static final int RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS != null ? OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS : 0; @@ -34,7 +34,7 @@ public class SuggestionsInfoCompatUtils { /** * Returns the flag value of the attributes of the suggestions that can be obtained by - * {@link #getSuggestionsAttributes}: this tells that the text service thinks + * {@link SuggestionsInfo#getSuggestionsAttributes()}: this tells that the text service thinks * the result suggestions include highly recommended ones. */ public static int getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS() { diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java index 16b4eafc9..275aacf36 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java @@ -42,13 +42,13 @@ public interface KeyboardActionListener { * * @param primaryCode this is the code of the key that was pressed * @param x x-coordinate pixel of touched event. If {@link #onCodeInput} is not called by - * {@link PointerTracker#onTouchEvent} or so, the value should be - * {@link #NOT_A_TOUCH_COORDINATE}. If it's called on insertion from the suggestion - * strip, it should be {@link #SUGGESTION_STRIP_COORDINATE}. + * {@link PointerTracker} or so, the value should be {@link #NOT_A_TOUCH_COORDINATE}. + * If it's called on insertion from the suggestion strip, it should be + * {@link #SUGGESTION_STRIP_COORDINATE}. * @param y y-coordinate pixel of touched event. If {@link #onCodeInput} is not called by - * {@link PointerTracker#onTouchEvent} or so, the value should be - * {@link #NOT_A_TOUCH_COORDINATE}. If it's called on insertion from the suggestion - * strip, it should be {@link #SUGGESTION_STRIP_COORDINATE}. + * {@link PointerTracker} or so, the value should be {@link #NOT_A_TOUCH_COORDINATE}. + * If it's called on insertion from the suggestion strip, it should be + * {@link #SUGGESTION_STRIP_COORDINATE}. */ public void onCodeInput(int primaryCode, int x, int y); diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index 8ec440500..311d3dc9d 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -252,7 +252,7 @@ public class BinaryDictionaryFileDumper { * also apply. * * @param input the stream to be copied. - * @param outputFile an outputstream to copy the data to. + * @param output an output stream to copy the data to. */ private static void checkMagicAndCopyFileTo(final BufferedInputStream input, final FileOutputStream output) throws FileNotFoundException, IOException { diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java index 79bf33850..9d26a2343 100644 --- a/java/src/com/android/inputmethod/latin/Dictionary.java +++ b/java/src/com/android/inputmethod/latin/Dictionary.java @@ -38,7 +38,7 @@ public abstract class Dictionary { /** * Interface to be implemented by classes requesting words to be fetched from the dictionary. - * @see #getWords(WordComposer, WordCallback) + * @see #getWords(WordComposer, WordCallback, ProximityInfo) */ public interface WordCallback { /** diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 86c153958..9f9f6b87d 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -68,7 +68,6 @@ import com.android.inputmethod.keyboard.KeyboardId; import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardView; import com.android.inputmethod.keyboard.LatinKeyboardView; -import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils; import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.latin.suggestions.SuggestionsView; diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java index 732efadd6..dc0868e7c 100644 --- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java +++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java @@ -16,7 +16,6 @@ package com.android.inputmethod.latin; -import android.content.Context; import android.content.SharedPreferences; import android.view.inputmethod.EditorInfo; diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 0694ffe77..7f3be8584 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -178,8 +178,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } if (prefs != null) { sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); + prefs.registerOnSharedPreferenceChangeListener(this); } - prefs.registerOnSharedPreferenceChangeListener(this); } /** diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index 555a49ef4..bd8532ebd 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -144,9 +144,7 @@ public class WordComposer { } /** - * Add a new keystroke, with codes[0] containing the pressed key's unicode and the rest of - * the array containing unicode for adjacent keys, sorted by reducing probability/proximity. - * @param codes the array of unicode values + * Add a new keystroke, with the pressed key's code point with the touch point coordinates. */ private void add(int primaryCode, int keyX, int keyY) { final int newIndex = size(); -- cgit v1.2.3-83-g751a From 347fcab043f4822cbe182ea9ec9c0237a9101fb5 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Thu, 29 Mar 2012 12:20:01 -0700 Subject: improve ResearchLogger performance also demonstrate proposed logpoint invocation Bug: 6188932 Change-Id: Ib6a7a196fe2e5f8184d26d1e0e3e91b404454112 --- .../com/android/inputmethod/latin/LatinIME.java | 13 ++++++++++++ .../android/inputmethod/latin/ResearchLogger.java | 23 +++++++++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index e6094d9e1..8b32be937 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -792,6 +792,19 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, composingSpanEnd); + if (ProductionFlag.IS_EXPERIMENTAL) { + if (ResearchLogger.UnsLogGroup.ON_UPDATE_SELECTION.isEnabled) { + final String s = "onUpdateSelection: oss=" + oldSelStart + + ", ose=" + oldSelEnd + + ", lss=" + mLastSelectionStart + + ", lse=" + mLastSelectionEnd + + ", nss=" + newSelStart + + ", nse=" + newSelEnd + + ", cs=" + composingSpanStart + + ", ce=" + composingSpanEnd; + ResearchLogger.logUnstructured(ResearchLogger.UnsLogGroup.ON_UPDATE_SELECTION, s); + } + } if (DEBUG) { Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart + ", ose=" + oldSelEnd diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 570333cb7..c5fb61f78 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -259,20 +259,33 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang write(LogGroup.STATE_CHANGE, subgroup + "\t" + details); } + public static enum UnsLogGroup { + // TODO: expand to include one flag per log point + // TODO: support selective enabling of flags + ON_UPDATE_SELECTION; + + public boolean isEnabled = true; + } + + public static void logUnstructured(UnsLogGroup logGroup, String details) { + } + private void write(final LogGroup logGroup, final String log) { + // TODO: rewrite in native for better performance mLoggingHandler.post(new Runnable() { @Override public void run() { final long currentTime = System.currentTimeMillis(); - mDate.setTime(currentTime); final long upTime = SystemClock.uptimeMillis(); - - final String printString = String.format("%s\t%d\t%s\t%s\n", - mDateFormat.format(mDate), upTime, logGroup.mLogString, log); + final StringBuilder builder = new StringBuilder(); + builder.append(currentTime); + builder.append('\t'); builder.append(upTime); + builder.append('\t'); builder.append(logGroup.mLogString); + builder.append('\t'); builder.append(log); if (LatinImeLogger.sDBG) { Log.d(TAG, "Write: " + '[' + logGroup.mLogString + ']' + log); } - if (mLogFileManager.append(printString)) { + if (mLogFileManager.append(builder.toString())) { // success } else { if (LatinImeLogger.sDBG) { -- cgit v1.2.3-83-g751a From ac9e87c03ebbcbd70dd051a30ebf98d6baebedfc Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Fri, 30 Mar 2012 13:15:46 -0700 Subject: add more data collection points to ResearchLogger the new points are all at Log.x() positions; only those appearing directly related to user input were added. Bug: 6188932 Change-Id: I618bcd07b22c9efc794745678b073afe1e79a697 --- .../inputmethod/keyboard/LatinKeyboardView.java | 25 +- .../inputmethod/keyboard/PointerTracker.java | 23 ++ .../keyboard/SuddenJumpingTouchEventHandler.java | 5 + .../keyboard/internal/AlphabetShiftState.java | 12 + .../keyboard/internal/KeyboardState.java | 45 +++ .../android/inputmethod/latin/AutoCorrection.java | 11 + .../com/android/inputmethod/latin/LatinIME.java | 27 +- .../android/inputmethod/latin/ResearchLogger.java | 441 ++++++++++++++++++--- 8 files changed, 513 insertions(+), 76 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 2689e6e13..98da1eb65 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -555,6 +555,9 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke * method on the base class if the subclass doesn't wish to handle the call. */ protected boolean onLongPress(Key parentKey, PointerTracker tracker) { + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinKeyboardView_onLongPress(); + } final int primaryCode = parentKey.mCode; if (parentKey.hasEmbeddedMoreKey()) { final int embeddedCode = KeySpecParser.getCode(getResources(), parentKey.mMoreKeys[0]); @@ -695,17 +698,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } } if (ProductionFlag.IS_EXPERIMENTAL) { - if (ResearchLogger.sIsLogging) { - // TODO: remove redundant calculations of size and pressure by - // removing UsabilityStudyLog code once the ResearchLogger is mature enough - final float size = me.getSize(index); - final float pressure = me.getPressure(index); - if (action != MotionEvent.ACTION_MOVE) { - // Skip ACTION_MOVE events as they are logged below - ResearchLogger.getInstance().logMotionEvent(action, eventTime, id, x, y, - size, pressure); - } - } + ResearchLogger.latinKeyboardView_processMotionEvent(me, action, eventTime, index, id, + x, y); } if (mKeyTimerHandler.isInKeyRepeat()) { @@ -773,13 +767,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke + pointerSize + "," + pointerPressure); } if (ProductionFlag.IS_EXPERIMENTAL) { - if (ResearchLogger.sIsLogging) { - // TODO: earlier comment about redundant calculations applies here too - final float pointerSize = me.getSize(i); - final float pointerPressure = me.getPressure(i); - ResearchLogger.getInstance().logMotionEvent(action, eventTime, pointerId, - px, py, pointerSize, pointerPressure); - } + ResearchLogger.latinKeyboardView_processMotionEvent(me, action, eventTime, + i, pointerId, px, py); } } } else { diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index ec9081681..24ab54730 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -23,6 +23,8 @@ import android.widget.TextView; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.ResearchLogger; +import com.android.inputmethod.latin.define.ProductionFlag; import java.util.ArrayList; @@ -235,6 +237,10 @@ public class PointerTracker { + " ignoreModifier=" + ignoreModifierKey + " enabled=" + key.isEnabled()); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange(key, + ignoreModifierKey); + } if (ignoreModifierKey) { return false; } @@ -259,6 +265,10 @@ public class PointerTracker { + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode + " enabled=" + key.isEnabled()); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_callListenerOnCodeInput(key, x, y, ignoreModifierKey, + altersCode, code); + } if (ignoreModifierKey) { return; } @@ -284,6 +294,10 @@ public class PointerTracker { + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey + " enabled="+ key.isEnabled()); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_callListenerOnRelease(key, primaryCode, withSliding, + ignoreModifierKey); + } if (ignoreModifierKey) { return; } @@ -295,6 +309,9 @@ public class PointerTracker { private void callListenerOnCancelInput() { if (DEBUG_LISTENER) Log.d(TAG, "onCancelInput"); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_callListenerOnCancelInput(); + } mListener.onCancelInput(); } @@ -479,6 +496,9 @@ public class PointerTracker { if (DEBUG_MODE) Log.w(TAG, "onDownEvent: ignore potential noise: time=" + deltaT + " distance=" + distanceSquared); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_onDownEvent(deltaT, distanceSquared); + } mKeyAlreadyProcessed = true; return; } @@ -583,6 +603,9 @@ public class PointerTracker { if (DEBUG_MODE) Log.w(TAG, String.format("onMoveEvent: sudden move is translated to " + "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y)); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_onMoveEvent(x, y, lastX, lastY); + } onUpEventInternal(lastX, lastY, eventTime); onDownEventInternal(x, y, eventTime); } else { diff --git a/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java b/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java index 347383f95..107138395 100644 --- a/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java +++ b/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java @@ -22,7 +22,9 @@ import android.view.MotionEvent; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.ResearchLogger; import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.define.ProductionFlag; public class SuddenJumpingTouchEventHandler { private static final String TAG = SuddenJumpingTouchEventHandler.class.getSimpleName(); @@ -141,6 +143,9 @@ public class SuddenJumpingTouchEventHandler { if (handleSuddenJumping(me)) { if (DEBUG_MODE) Log.w(TAG, "onTouchEvent: ignore sudden jump " + me); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.suddenJumpingTouchEventHandler_onTouchEvent(me); + } return true; } return mView.processMotionEvent(me); diff --git a/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java index 5712df1fc..392afca97 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java @@ -18,6 +18,9 @@ package com.android.inputmethod.keyboard.internal; import android.util.Log; +import com.android.inputmethod.latin.ResearchLogger; +import com.android.inputmethod.latin.define.ProductionFlag; + public class AlphabetShiftState { private static final String TAG = AlphabetShiftState.class.getSimpleName(); private static final boolean DEBUG = false; @@ -59,6 +62,9 @@ public class AlphabetShiftState { } if (DEBUG) Log.d(TAG, "setShifted(" + newShiftState + "): " + toString(oldState) + " > " + this); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.alphabetShiftState_setShifted(newShiftState, oldState, this); + } } public void setShiftLocked(boolean newShiftLockState) { @@ -78,6 +84,9 @@ public class AlphabetShiftState { if (DEBUG) Log.d(TAG, "setShiftLocked(" + newShiftLockState + "): " + toString(oldState) + " > " + this); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.alphabetShiftState_setShiftLocked(newShiftLockState, oldState, this); + } } public void setAutomaticShifted() { @@ -85,6 +94,9 @@ public class AlphabetShiftState { mState = AUTOMATIC_SHIFTED; if (DEBUG) Log.d(TAG, "setAutomaticShifted: " + toString(oldState) + " > " + this); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.alphabetShiftState_setAutomaticShifted(oldState, this); + } } public boolean isShiftedOrShiftLocked() { diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index 18a3f9794..6949c9d12 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -20,6 +20,8 @@ import android.text.TextUtils; import android.util.Log; import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.latin.ResearchLogger; +import com.android.inputmethod.latin.define.ProductionFlag; /** * Keyboard state machine. @@ -139,6 +141,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onSaveKeyboardState: saved=" + state + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onSaveKeyboardState(this, state.toString()); + } } private void onRestoreKeyboardState() { @@ -146,6 +151,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onRestoreKeyboardState: saved=" + state + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onRestoreKeyboardState(this, state.toString()); + } if (!state.mIsValid || state.mIsAlphabetMode) { setAlphabetKeyboard(); } else { @@ -178,6 +186,9 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode) + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_setShifted(this, shiftModeToString(shiftMode)); + } if (!mIsAlphabetMode) return; final int prevShiftMode; if (mAlphabetShiftState.isAutomaticShifted()) { @@ -217,6 +228,9 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setShiftLocked: shiftLocked=" + shiftLocked + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_setShiftLocked(this, shiftLocked); + } if (!mIsAlphabetMode) return; if (shiftLocked && (!mAlphabetShiftState.isShiftLocked() || mAlphabetShiftState.isShiftLockShifted())) { @@ -232,6 +246,9 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "toggleAlphabetAndSymbols: " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_toggleAlphabetAndSymbols(this); + } if (mIsAlphabetMode) { mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked(); if (mPrevSymbolsKeyboardWasShifted) { @@ -262,6 +279,10 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setAlphabetKeyboard"); } + + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_setAlphabetKeyboard(); + } mSwitchActions.setAlphabetKeyboard(); mIsAlphabetMode = true; mIsSymbolShifted = false; @@ -273,6 +294,9 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setSymbolsKeyboard"); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_setSymbolsKeyboard(); + } mSwitchActions.setSymbolsKeyboard(); mIsAlphabetMode = false; mIsSymbolShifted = false; @@ -285,6 +309,9 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setSymbolsShiftedKeyboard"); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_setSymbolsShiftedKeyboard(); + } mSwitchActions.setSymbolsShiftedKeyboard(); mIsAlphabetMode = false; mIsSymbolShifted = true; @@ -297,6 +324,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code) + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onPressKey(code, this); + } if (code == Keyboard.CODE_SHIFT) { onPressShift(); } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { @@ -314,6 +344,9 @@ public class KeyboardState { Log.d(TAG, "onReleaseKey: code=" + Keyboard.printableCode(code) + " sliding=" + withSliding + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onReleaseKey(this, code, withSliding); + } if (code == Keyboard.CODE_SHIFT) { onReleaseShift(withSliding); } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { @@ -345,6 +378,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onLongPressTimeout(code, this); + } if (mIsAlphabetMode && code == Keyboard.CODE_SHIFT) { if (mAlphabetShiftState.isShiftLocked()) { setShiftLocked(false); @@ -363,6 +399,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onUpdateShiftState(this, autoCaps); + } updateAlphabetShiftState(autoCaps); } @@ -481,6 +520,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onCancelInput: single=" + isSinglePointer + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onCancelInput(isSinglePointer, this); + } // Switch back to the previous keyboard mode if the user cancels sliding input. if (isSinglePointer) { if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) { @@ -512,6 +554,9 @@ public class KeyboardState { + " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onCodeInput(code, isSinglePointer, autoCaps, this); + } switch (mSwitchState) { case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java index 38444a10c..520177afe 100644 --- a/java/src/com/android/inputmethod/latin/AutoCorrection.java +++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java @@ -21,6 +21,8 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import android.text.TextUtils; import android.util.Log; +import com.android.inputmethod.latin.define.ProductionFlag; + import java.util.ArrayList; import java.util.HashMap; @@ -115,10 +117,19 @@ public class AutoCorrection { + autoCorrectionSuggestionScore + ", " + normalizedScore + "(" + autoCorrectionThreshold + ")"); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.autoCorrection_hasAutoCorrectionForBinaryDictionary(consideredWord, + autoCorrectionThreshold, autoCorrectionSuggestion.toString(), + autoCorrectionSuggestionScore, normalizedScore); + } if (normalizedScore >= autoCorrectionThreshold) { if (DBG) { Log.d(TAG, "Auto corrected by S-threshold."); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger + .autoCorrection_hasAutoCorrectionForBinaryDictionary_bySthreshold(); + } return true; } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index f5c09974e..e0fa2f838 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -665,6 +665,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen + String.format("inputType=0x%08x imeOptions=0x%08x", editorInfo.inputType, editorInfo.imeOptions)); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_onStartInputViewInternal(editorInfo); + } if (StringUtils.inPrivateImeOptions(null, IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)) { Log.w(TAG, "Deprecated private IME option specified: " + editorInfo.privateImeOptions); @@ -762,19 +765,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, composingSpanEnd); - if (ProductionFlag.IS_EXPERIMENTAL) { - if (ResearchLogger.UnsLogGroup.ON_UPDATE_SELECTION.isEnabled) { - final String s = "onUpdateSelection: oss=" + oldSelStart - + ", ose=" + oldSelEnd - + ", lss=" + mLastSelectionStart - + ", lse=" + mLastSelectionEnd - + ", nss=" + newSelStart - + ", nse=" + newSelEnd - + ", cs=" + composingSpanStart - + ", ce=" + composingSpanEnd; - ResearchLogger.logUnstructured(ResearchLogger.UnsLogGroup.ON_UPDATE_SELECTION, s); - } - } if (DEBUG) { Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart + ", ose=" + oldSelEnd @@ -785,6 +775,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen + ", cs=" + composingSpanStart + ", ce=" + composingSpanEnd); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_onUpdateSelection(mLastSelectionStart, mLastSelectionEnd, + oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, + composingSpanEnd); + } // TODO: refactor the following code to be less contrived. // "newSelStart != composingSpanEnd" || "newSelEnd != composingSpanEnd" means @@ -886,6 +881,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions); + } if (mInputAttributes.mApplicationSpecifiedCompletionOn) { mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; if (applicationSpecifiedCompletions == null) { @@ -1660,6 +1658,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (DEBUG) { Log.d(TAG, "Switch to keyboard view."); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_switchToKeyboardView(); + } View v = mKeyboardSwitcher.getKeyboardView(); if (v != null) { // Confirms that the keyboard view doesn't have parent view. diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index c5fb61f78..182a7bc3e 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -25,15 +25,20 @@ import android.os.SystemClock; import android.text.TextUtils; import android.util.Log; import android.view.MotionEvent; +import android.view.inputmethod.CompletionInfo; +import android.view.inputmethod.EditorInfo; +import com.android.inputmethod.keyboard.Key; +import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.keyboard.internal.AlphabetShiftState; +import com.android.inputmethod.keyboard.internal.KeyboardState; +import com.android.inputmethod.latin.define.ProductionFlag; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintWriter; -import java.text.SimpleDateFormat; -import java.util.Date; /** * Logs the use of the LatinIME keyboard. @@ -46,13 +51,12 @@ import java.util.Date; public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = ResearchLogger.class.getSimpleName(); private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; + private static final boolean DEBUG = false; private static final ResearchLogger sInstance = new ResearchLogger(new LogFileManager()); public static boolean sIsLogging = false; /* package */ final Handler mLoggingHandler; private InputMethodService mIms; - private final Date mDate; - private final SimpleDateFormat mDateFormat; /** * Isolates management of files. This variable should never be null, but can be changed @@ -79,35 +83,36 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang /* package */ LogFileManager() { } - public void init(InputMethodService ims) { + public void init(final InputMethodService ims) { mIms = ims; } - public synchronized void createLogFile() { + public synchronized boolean createLogFile() { try { - createLogFile(DEFAULT_LOG_DIRECTORY, DEFAULT_FILENAME); - } catch (FileNotFoundException e) { + return createLogFile(DEFAULT_LOG_DIRECTORY, DEFAULT_FILENAME); + } catch (final FileNotFoundException e) { Log.w(TAG, e); + return false; } } - public synchronized void createLogFile(String dir, String filename) + public synchronized boolean createLogFile(final String dir, final String filename) throws FileNotFoundException { if (mIms == null) { Log.w(TAG, "InputMethodService is not configured. Logging is off."); - return; + return false; } - File filesDir = mIms.getFilesDir(); + final File filesDir = mIms.getFilesDir(); if (filesDir == null || !filesDir.exists()) { Log.w(TAG, "Storage directory does not exist. Logging is off."); - return; + return false; } - File directory = new File(filesDir, dir); + final File directory = new File(filesDir, dir); if (!directory.exists()) { - boolean wasCreated = directory.mkdirs(); + final boolean wasCreated = directory.mkdirs(); if (!wasCreated) { Log.w(TAG, "Log directory cannot be created. Logging is off."); - return; + return false; } } @@ -120,16 +125,23 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang append = false; } mPrintWriter = new PrintWriter(new FileOutputStream(mFile, append), true); + return true; } - public synchronized boolean append(String s) { + public synchronized boolean append(final String s) { if (mPrintWriter == null) { - Log.w(TAG, "PrintWriter is null"); - return false; - } else { - mPrintWriter.print(s); - return !mPrintWriter.checkError(); + if (DEBUG) { + Log.w(TAG, "PrintWriter is null... attempting to create default log file"); + } + if (!createLogFile()) { + if (DEBUG) { + Log.w(TAG, "Failed to create log file. Not logging."); + return false; + } + } } + mPrintWriter.print(s); + return !mPrintWriter.checkError(); } public synchronized void reset() { @@ -152,11 +164,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - private ResearchLogger(LogFileManager logFileManager) { - mDate = new Date(); - mDateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss.SSSZ"); - - HandlerThread handlerThread = new HandlerThread("ResearchLogger logging task", + private ResearchLogger(final LogFileManager logFileManager) { + final HandlerThread handlerThread = new HandlerThread("ResearchLogger logging task", Process.THREAD_PRIORITY_BACKGROUND); handlerThread.start(); mLoggingHandler = new Handler(handlerThread.getLooper()); @@ -167,11 +176,11 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang return sInstance; } - public static void init(InputMethodService ims, SharedPreferences prefs) { + public static void init(final InputMethodService ims, final SharedPreferences prefs) { sInstance.initInternal(ims, prefs); } - public void initInternal(InputMethodService ims, SharedPreferences prefs) { + public void initInternal(final InputMethodService ims, final SharedPreferences prefs) { mIms = ims; if (mLogFileManager != null) { mLogFileManager.init(ims); @@ -188,7 +197,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang * * @throws IllegalArgumentException if logFileManager is null */ - void setLogFileManager(LogFileManager manager) { + void setLogFileManager(final LogFileManager manager) { if (manager == null) { throw new IllegalArgumentException("warning: trying to set null logFileManager"); } else { @@ -203,11 +212,12 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang MOTION_EVENT("m"), KEY("k"), CORRECTION("c"), - STATE_CHANGE("s"); + STATE_CHANGE("s"), + UNSTRUCTURED("u"); private final String mLogString; - private LogGroup(String logString) { + private LogGroup(final String logString) { mLogString = logString; } } @@ -226,7 +236,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang default: eventTag = "[Action" + action + "]"; break; } if (!TextUtils.isEmpty(eventTag)) { - StringBuilder sb = new StringBuilder(); + final StringBuilder sb = new StringBuilder(); sb.append(eventTag); sb.append('\t'); sb.append(eventTime); sb.append('\t'); sb.append(id); @@ -238,7 +248,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - public void logKeyEvent(int code, int x, int y) { + public void logKeyEvent(final int code, final int x, final int y) { final StringBuilder sb = new StringBuilder(); sb.append(Keyboard.printableCode(code)); sb.append('\t'); sb.append(x); @@ -246,7 +256,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang write(LogGroup.KEY, sb.toString()); } - public void logCorrection(String subgroup, String before, String after, int position) { + public void logCorrection(final String subgroup, final String before, final String after, + final int position) { final StringBuilder sb = new StringBuilder(); sb.append(subgroup); sb.append('\t'); sb.append(before); @@ -255,19 +266,62 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang write(LogGroup.CORRECTION, sb.toString()); } - public void logStateChange(String subgroup, String details) { + public void logStateChange(final String subgroup, final String details) { write(LogGroup.STATE_CHANGE, subgroup + "\t" + details); } - public static enum UnsLogGroup { - // TODO: expand to include one flag per log point - // TODO: support selective enabling of flags - ON_UPDATE_SELECTION; - - public boolean isEnabled = true; + public static class UnsLogGroup { + private static final boolean DEFAULT_ENABLED = true; + + private static final boolean ALPHABETSHIFTSTATE_SETSHIFTED_ENABLED = DEFAULT_ENABLED; + private static final boolean ALPHABETSHIFTSTATE_SETSHIFTLOCKED_ENABLED = DEFAULT_ENABLED; + private static final boolean ALPHABETSHIFTSTATE_SETAUTOMATICSHIFTED_ENABLED + = DEFAULT_ENABLED; + private static final boolean AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_ENABLED + = DEFAULT_ENABLED; + private static final boolean + AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_BYSTHRESHOLD_ENABLED + = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONCANCELINPUT_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONCODEINPUT_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONPRESSKEY_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONRELEASEKEY_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONRESTOREKEYBOARDSTATE_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONSAVEKEYBOARDSTATE_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONUPDATESHIFTSTATE_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_SETALPHABETKEYBOARD_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_SETSHIFTED_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_SETSHIFTLOCKED_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_SETSYMBOLSKEYBOARD_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_SETSYMBOLSSHIFTEDKEYBOARD_ENABLED + = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED + = DEFAULT_ENABLED; + private static final boolean LATINIME_ONDISPLAYCOMPLETIONS_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_ONUPDATESELECTION_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED + = DEFAULT_ENABLED; + private static final boolean POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED + = DEFAULT_ENABLED; + private static final boolean POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED + = DEFAULT_ENABLED; + private static final boolean + POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED + = DEFAULT_ENABLED; + private static final boolean POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED = DEFAULT_ENABLED; + private static final boolean POINTERTRACKER_ONDOWNEVENT_ENABLED = DEFAULT_ENABLED; + private static final boolean POINTERTRACKER_ONMOVEEVENT_ENABLED = DEFAULT_ENABLED; + private static final boolean SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED + = DEFAULT_ENABLED; } - public static void logUnstructured(UnsLogGroup logGroup, String details) { + public static void logUnstructured(String logGroup, final String details) { + // TODO: improve performance by making entire class static and/or implementing natively + getInstance().write(LogGroup.UNSTRUCTURED, logGroup + "\t" + details); } private void write(final LogGroup logGroup, final String log) { @@ -282,13 +336,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang builder.append('\t'); builder.append(upTime); builder.append('\t'); builder.append(logGroup.mLogString); builder.append('\t'); builder.append(log); - if (LatinImeLogger.sDBG) { + builder.append('\n'); + if (DEBUG) { Log.d(TAG, "Write: " + '[' + logGroup.mLogString + ']' + log); } if (mLogFileManager.append(builder.toString())) { // success } else { - if (LatinImeLogger.sDBG) { + if (DEBUG) { Log.w(TAG, "Unable to write to log."); } } @@ -300,7 +355,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mLoggingHandler.post(new Runnable() { @Override public void run() { - if (LatinImeLogger.sDBG) { + if (DEBUG) { Log.d(TAG, "Delete log file."); } mLogFileManager.reset(); @@ -315,4 +370,300 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); } + + public static void alphabetShiftState_setShifted(final boolean newShiftState, + final int oldState, final AlphabetShiftState alphabetShiftState) { + if (UnsLogGroup.ALPHABETSHIFTSTATE_SETSHIFTED_ENABLED) { + final String s = "setShifted(" + newShiftState + "): " + oldState + + " > " + alphabetShiftState; + logUnstructured("AlphabetShiftState_setShifted", s); + } + } + + public static void alphabetShiftState_setShiftLocked(final boolean newShiftLockState, + final int oldState, final AlphabetShiftState alphabetShiftState) { + if (UnsLogGroup.ALPHABETSHIFTSTATE_SETSHIFTLOCKED_ENABLED) { + final String s = "setShiftLocked(" + newShiftLockState + "): " + + oldState + " > " + alphabetShiftState; + logUnstructured("AlphabetShiftState_setShiftLocked", s); + } + } + + public static void alphabetShiftState_setAutomaticShifted(final int oldState, + final AlphabetShiftState alphabetShiftState) { + if (UnsLogGroup.ALPHABETSHIFTSTATE_SETAUTOMATICSHIFTED_ENABLED) { + final String s = "setAutomaticShifted: " + oldState + " > " + alphabetShiftState; + logUnstructured("AlphabetShiftState_setAutomaticShifted", s); + } + } + + public static void autoCorrection_hasAutoCorrectionForBinaryDictionary( + final CharSequence consideredWord, final double autoCorrectionThreshold, + final CharSequence autoCorrectionSuggestion, final int autoCorrectionSuggestionScore, + final double normalizedScore) { + if (UnsLogGroup.AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_ENABLED) { + final String s = "Normalized " + consideredWord + "," + + autoCorrectionSuggestion + "," + autoCorrectionSuggestionScore + + ", " + normalizedScore + "(" + autoCorrectionThreshold + ")"; + logUnstructured("AutoCorrection_hasAutoCorrectionForBinaryDictionary", s); + } + } + + public static void autoCorrection_hasAutoCorrectionForBinaryDictionary_bySthreshold() { + if (UnsLogGroup.AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_BYSTHRESHOLD_ENABLED) { + final String s = "Auto corrected by S-threshold."; + logUnstructured("AutoCorrection_hasAutoCorrectionForBinaryDictionar_bySthreshold", s); + } + } + + public static void keyboardState_onCancelInput(final boolean isSinglePointer, + final KeyboardState keyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONCANCELINPUT_ENABLED) { + final String s = "onCancelInput: single=" + isSinglePointer + " " + keyboardState; + logUnstructured("KeyboardState_onCancelInput", s); + } + } + + public static void keyboardState_onCodeInput( + final int code, final boolean isSinglePointer, final boolean autoCaps, + final KeyboardState keyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONCODEINPUT_ENABLED) { + final String s = "onCodeInput: code=" + Keyboard.printableCode(code) + + " single=" + isSinglePointer + + " autoCaps=" + autoCaps + " " + keyboardState; + logUnstructured("KeyboardState_onCodeInput", s); + } + } + + public static void keyboardState_onLongPressTimeout(final int code, + final KeyboardState keyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED) { + final String s = "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + + keyboardState; + logUnstructured("KeyboardState_onLongPressTimeout", s); + } + } + + public static void keyboardState_onPressKey(final int code, + final KeyboardState keyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONPRESSKEY_ENABLED) { + final String s = "onPressKey: code=" + Keyboard.printableCode(code) + " " + + keyboardState; + logUnstructured("KeyboardState_onPressKey", s); + } + } + + public static void keyboardState_onReleaseKey(final KeyboardState keyboardState, final int code, + final boolean withSliding) { + if (UnsLogGroup.KEYBOARDSTATE_ONRELEASEKEY_ENABLED) { + final String s = "onReleaseKey: code=" + Keyboard.printableCode(code) + + " sliding=" + withSliding + " " + keyboardState; + logUnstructured("KeyboardState_onReleaseKey", s); + } + } + + public static void keyboardState_onRestoreKeyboardState(final KeyboardState keyboardState, + final String savedKeyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONRESTOREKEYBOARDSTATE_ENABLED) { + final String s = "onRestoreKeyboardState: saved=" + savedKeyboardState + " " + + keyboardState; + logUnstructured("KeyboardState_onRestoreKeyboardState", s); + } + } + + public static void keyboardState_onSaveKeyboardState(final KeyboardState keyboardState, + final String savedKeyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONSAVEKEYBOARDSTATE_ENABLED) { + final String s = "onSaveKeyboardState: saved=" + savedKeyboardState + " " + + keyboardState; + logUnstructured("KeyboardState_onSaveKeyboardState", s); + } + } + + public static void keyboardState_onUpdateShiftState(final KeyboardState keyboardState, + final boolean autoCaps) { + if (UnsLogGroup.KEYBOARDSTATE_ONUPDATESHIFTSTATE_ENABLED) { + final String s = "onUpdateShiftState: autoCaps=" + autoCaps + " " + keyboardState; + logUnstructured("KeyboardState_onUpdateShiftState", s); + } + } + + public static void keyboardState_setAlphabetKeyboard() { + if (UnsLogGroup.KEYBOARDSTATE_SETALPHABETKEYBOARD_ENABLED) { + final String s = "setAlphabetKeyboard"; + logUnstructured("KeyboardState_setAlphabetKeyboard", s); + } + } + + public static void keyboardState_setShifted(final KeyboardState keyboardState, + final String shiftMode) { + if (UnsLogGroup.KEYBOARDSTATE_SETSHIFTED_ENABLED) { + final String s = "setShifted: shiftMode=" + shiftMode + " " + keyboardState; + logUnstructured("KeyboardState_setShifted", s); + } + } + + public static void keyboardState_setShiftLocked(final KeyboardState keyboardState, + final boolean shiftLocked) { + if (UnsLogGroup.KEYBOARDSTATE_SETSHIFTLOCKED_ENABLED) { + final String s = "setShiftLocked: shiftLocked=" + shiftLocked + " " + keyboardState; + logUnstructured("KeyboardState_setShiftLocked", s); + } + } + + public static void keyboardState_setSymbolsKeyboard() { + if (UnsLogGroup.KEYBOARDSTATE_SETSYMBOLSKEYBOARD_ENABLED) { + final String s = "setSymbolsKeyboard"; + logUnstructured("KeyboardState_setSymbolsKeyboard", s); + } + } + + public static void keyboardState_setSymbolsShiftedKeyboard() { + if (UnsLogGroup.KEYBOARDSTATE_SETSYMBOLSSHIFTEDKEYBOARD_ENABLED) { + final String s = "setSymbolsShiftedKeyboard"; + logUnstructured("KeyboardState_setSymbolsShiftedKeyboard", s); + } + } + + public static void keyboardState_toggleAlphabetAndSymbols(final KeyboardState keyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED) { + final String s = "toggleAlphabetAndSymbols: " + keyboardState; + logUnstructured("KeyboardState_toggleAlphabetAndSymbols", s); + } + } + + public static void latinIME_onDisplayCompletions( + final CompletionInfo[] applicationSpecifiedCompletions) { + if (UnsLogGroup.LATINIME_ONDISPLAYCOMPLETIONS_ENABLED) { + final StringBuilder builder = new StringBuilder(); + builder.append("Received completions:"); + if (applicationSpecifiedCompletions != null) { + for (int i = 0; i < applicationSpecifiedCompletions.length; i++) { + builder.append(" #"); + builder.append(i); + builder.append(": "); + builder.append(applicationSpecifiedCompletions[i]); + builder.append("\n"); + } + } + logUnstructured("LatinIME_onDisplayCompletions", builder.toString()); + } + } + + public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo) { + if (UnsLogGroup.LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED) { + final StringBuilder builder = new StringBuilder(); + builder.append("onStartInputView: editorInfo:"); + builder.append("inputType="); + builder.append(editorInfo.inputType); + builder.append("imeOptions="); + builder.append(editorInfo.imeOptions); + logUnstructured("LatinIME_onStartInputViewInternal", builder.toString()); + } + } + + public static void latinIME_onUpdateSelection(final int lastSelectionStart, + final int lastSelectionEnd, final int oldSelStart, final int oldSelEnd, + final int newSelStart, final int newSelEnd, final int composingSpanStart, + final int composingSpanEnd) { + if (UnsLogGroup.LATINIME_ONUPDATESELECTION_ENABLED) { + final String s = "onUpdateSelection: oss=" + oldSelStart + + ", ose=" + oldSelEnd + + ", lss=" + lastSelectionStart + + ", lse=" + lastSelectionEnd + + ", nss=" + newSelStart + + ", nse=" + newSelEnd + + ", cs=" + composingSpanStart + + ", ce=" + composingSpanEnd; + logUnstructured("LatinIME_onUpdateSelection", s); + } + } + + public static void latinIME_switchToKeyboardView() { + if (UnsLogGroup.LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED) { + final String s = "Switch to keyboard view."; + logUnstructured("LatinIME_switchToKeyboardView", s); + } + } + + public static void latinKeyboardView_onLongPress() { + if (UnsLogGroup.LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED) { + final String s = "long press detected"; + logUnstructured("LatinKeyboardView_onLongPress", s); + } + } + + public static void latinKeyboardView_processMotionEvent(MotionEvent me, int action, + long eventTime, int index, int id, int x, int y) { + if (UnsLogGroup.LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED) { + final float size = me.getSize(index); + final float pressure = me.getPressure(index); + if (action != MotionEvent.ACTION_MOVE) { + getInstance().logMotionEvent(action, eventTime, id, x, y, size, pressure); + } + } + } + + public static void pointerTracker_callListenerOnCancelInput() { + final String s = "onCancelInput"; + if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED) { + logUnstructured("PointerTracker_callListenerOnCancelInput", s); + } + } + + public static void pointerTracker_callListenerOnCodeInput(final Key key, final int x, + final int y, final boolean ignoreModifierKey, final boolean altersCode, + final int code) { + if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED) { + final String s = "onCodeInput: " + Keyboard.printableCode(code) + + " text=" + key.mOutputText + " x=" + x + " y=" + y + + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode + + " enabled=" + key.isEnabled(); + logUnstructured("PointerTracker_callListenerOnCodeInput", s); + } + } + + public static void pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange( + final Key key, final boolean ignoreModifierKey) { + if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED) { + final String s = "onPress : " + KeyDetector.printableCode(key) + + " ignoreModifier=" + ignoreModifierKey + + " enabled=" + key.isEnabled(); + logUnstructured("PointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange", s); + } + } + + public static void pointerTracker_callListenerOnRelease(final Key key, final int primaryCode, + final boolean withSliding, final boolean ignoreModifierKey) { + if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED) { + final String s = "onRelease : " + Keyboard.printableCode(primaryCode) + + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey + + " enabled="+ key.isEnabled(); + logUnstructured("PointerTracker_callListenerOnRelease", s); + } + } + + public static void pointerTracker_onDownEvent(long deltaT, int distanceSquared) { + if (UnsLogGroup.POINTERTRACKER_ONDOWNEVENT_ENABLED) { + final String s = "onDownEvent: ignore potential noise: time=" + deltaT + + " distance=" + distanceSquared; + logUnstructured("PointerTracker_onDownEvent", s); + } + } + + public static void pointerTracker_onMoveEvent(final int x, final int y, final int lastX, + final int lastY) { + if (UnsLogGroup.POINTERTRACKER_ONMOVEEVENT_ENABLED) { + final String s = String.format("onMoveEvent: sudden move is translated to " + + "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y); + logUnstructured("PointerTracker_onMoveEvent", s); + } + } + + public static void suddenJumpingTouchEventHandler_onTouchEvent(final MotionEvent me) { + if (UnsLogGroup.SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED) { + final String s = "onTouchEvent: ignore sudden jump " + me; + logUnstructured("SuddenJumpingTouchEventHandler_onTouchEvent", s); + } + } } -- cgit v1.2.3-83-g751a From d16bda4a4a307c8f8fd8d25c3984aaf307d49af5 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Fri, 6 Apr 2012 18:26:34 -0700 Subject: Revert "add more data collection points to ResearchLogger" This reverts commit ac9e87c03ebbcbd70dd051a30ebf98d6baebedfc --- .../inputmethod/keyboard/LatinKeyboardView.java | 25 +- .../inputmethod/keyboard/PointerTracker.java | 23 -- .../keyboard/SuddenJumpingTouchEventHandler.java | 5 - .../keyboard/internal/AlphabetShiftState.java | 12 - .../keyboard/internal/KeyboardState.java | 45 --- .../android/inputmethod/latin/AutoCorrection.java | 11 - .../com/android/inputmethod/latin/LatinIME.java | 27 +- .../android/inputmethod/latin/ResearchLogger.java | 441 +++------------------ 8 files changed, 76 insertions(+), 513 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 98da1eb65..2689e6e13 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -555,9 +555,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke * method on the base class if the subclass doesn't wish to handle the call. */ protected boolean onLongPress(Key parentKey, PointerTracker tracker) { - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.latinKeyboardView_onLongPress(); - } final int primaryCode = parentKey.mCode; if (parentKey.hasEmbeddedMoreKey()) { final int embeddedCode = KeySpecParser.getCode(getResources(), parentKey.mMoreKeys[0]); @@ -698,8 +695,17 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } } if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.latinKeyboardView_processMotionEvent(me, action, eventTime, index, id, - x, y); + if (ResearchLogger.sIsLogging) { + // TODO: remove redundant calculations of size and pressure by + // removing UsabilityStudyLog code once the ResearchLogger is mature enough + final float size = me.getSize(index); + final float pressure = me.getPressure(index); + if (action != MotionEvent.ACTION_MOVE) { + // Skip ACTION_MOVE events as they are logged below + ResearchLogger.getInstance().logMotionEvent(action, eventTime, id, x, y, + size, pressure); + } + } } if (mKeyTimerHandler.isInKeyRepeat()) { @@ -767,8 +773,13 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke + pointerSize + "," + pointerPressure); } if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.latinKeyboardView_processMotionEvent(me, action, eventTime, - i, pointerId, px, py); + if (ResearchLogger.sIsLogging) { + // TODO: earlier comment about redundant calculations applies here too + final float pointerSize = me.getSize(i); + final float pointerPressure = me.getPressure(i); + ResearchLogger.getInstance().logMotionEvent(action, eventTime, pointerId, + px, py, pointerSize, pointerPressure); + } } } } else { diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 24ab54730..ec9081681 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -23,8 +23,6 @@ import android.widget.TextView; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.LatinImeLogger; -import com.android.inputmethod.latin.ResearchLogger; -import com.android.inputmethod.latin.define.ProductionFlag; import java.util.ArrayList; @@ -237,10 +235,6 @@ public class PointerTracker { + " ignoreModifier=" + ignoreModifierKey + " enabled=" + key.isEnabled()); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange(key, - ignoreModifierKey); - } if (ignoreModifierKey) { return false; } @@ -265,10 +259,6 @@ public class PointerTracker { + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode + " enabled=" + key.isEnabled()); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.pointerTracker_callListenerOnCodeInput(key, x, y, ignoreModifierKey, - altersCode, code); - } if (ignoreModifierKey) { return; } @@ -294,10 +284,6 @@ public class PointerTracker { + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey + " enabled="+ key.isEnabled()); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.pointerTracker_callListenerOnRelease(key, primaryCode, withSliding, - ignoreModifierKey); - } if (ignoreModifierKey) { return; } @@ -309,9 +295,6 @@ public class PointerTracker { private void callListenerOnCancelInput() { if (DEBUG_LISTENER) Log.d(TAG, "onCancelInput"); - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.pointerTracker_callListenerOnCancelInput(); - } mListener.onCancelInput(); } @@ -496,9 +479,6 @@ public class PointerTracker { if (DEBUG_MODE) Log.w(TAG, "onDownEvent: ignore potential noise: time=" + deltaT + " distance=" + distanceSquared); - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.pointerTracker_onDownEvent(deltaT, distanceSquared); - } mKeyAlreadyProcessed = true; return; } @@ -603,9 +583,6 @@ public class PointerTracker { if (DEBUG_MODE) Log.w(TAG, String.format("onMoveEvent: sudden move is translated to " + "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y)); - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.pointerTracker_onMoveEvent(x, y, lastX, lastY); - } onUpEventInternal(lastX, lastY, eventTime); onDownEventInternal(x, y, eventTime); } else { diff --git a/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java b/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java index 107138395..347383f95 100644 --- a/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java +++ b/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java @@ -22,9 +22,7 @@ import android.view.MotionEvent; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.ResearchLogger; import com.android.inputmethod.latin.Utils; -import com.android.inputmethod.latin.define.ProductionFlag; public class SuddenJumpingTouchEventHandler { private static final String TAG = SuddenJumpingTouchEventHandler.class.getSimpleName(); @@ -143,9 +141,6 @@ public class SuddenJumpingTouchEventHandler { if (handleSuddenJumping(me)) { if (DEBUG_MODE) Log.w(TAG, "onTouchEvent: ignore sudden jump " + me); - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.suddenJumpingTouchEventHandler_onTouchEvent(me); - } return true; } return mView.processMotionEvent(me); diff --git a/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java index 392afca97..5712df1fc 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java @@ -18,9 +18,6 @@ package com.android.inputmethod.keyboard.internal; import android.util.Log; -import com.android.inputmethod.latin.ResearchLogger; -import com.android.inputmethod.latin.define.ProductionFlag; - public class AlphabetShiftState { private static final String TAG = AlphabetShiftState.class.getSimpleName(); private static final boolean DEBUG = false; @@ -62,9 +59,6 @@ public class AlphabetShiftState { } if (DEBUG) Log.d(TAG, "setShifted(" + newShiftState + "): " + toString(oldState) + " > " + this); - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.alphabetShiftState_setShifted(newShiftState, oldState, this); - } } public void setShiftLocked(boolean newShiftLockState) { @@ -84,9 +78,6 @@ public class AlphabetShiftState { if (DEBUG) Log.d(TAG, "setShiftLocked(" + newShiftLockState + "): " + toString(oldState) + " > " + this); - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.alphabetShiftState_setShiftLocked(newShiftLockState, oldState, this); - } } public void setAutomaticShifted() { @@ -94,9 +85,6 @@ public class AlphabetShiftState { mState = AUTOMATIC_SHIFTED; if (DEBUG) Log.d(TAG, "setAutomaticShifted: " + toString(oldState) + " > " + this); - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.alphabetShiftState_setAutomaticShifted(oldState, this); - } } public boolean isShiftedOrShiftLocked() { diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index 6949c9d12..18a3f9794 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -20,8 +20,6 @@ import android.text.TextUtils; import android.util.Log; import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.latin.ResearchLogger; -import com.android.inputmethod.latin.define.ProductionFlag; /** * Keyboard state machine. @@ -141,9 +139,6 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onSaveKeyboardState: saved=" + state + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onSaveKeyboardState(this, state.toString()); - } } private void onRestoreKeyboardState() { @@ -151,9 +146,6 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onRestoreKeyboardState: saved=" + state + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onRestoreKeyboardState(this, state.toString()); - } if (!state.mIsValid || state.mIsAlphabetMode) { setAlphabetKeyboard(); } else { @@ -186,9 +178,6 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode) + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_setShifted(this, shiftModeToString(shiftMode)); - } if (!mIsAlphabetMode) return; final int prevShiftMode; if (mAlphabetShiftState.isAutomaticShifted()) { @@ -228,9 +217,6 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setShiftLocked: shiftLocked=" + shiftLocked + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_setShiftLocked(this, shiftLocked); - } if (!mIsAlphabetMode) return; if (shiftLocked && (!mAlphabetShiftState.isShiftLocked() || mAlphabetShiftState.isShiftLockShifted())) { @@ -246,9 +232,6 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "toggleAlphabetAndSymbols: " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_toggleAlphabetAndSymbols(this); - } if (mIsAlphabetMode) { mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked(); if (mPrevSymbolsKeyboardWasShifted) { @@ -279,10 +262,6 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setAlphabetKeyboard"); } - - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_setAlphabetKeyboard(); - } mSwitchActions.setAlphabetKeyboard(); mIsAlphabetMode = true; mIsSymbolShifted = false; @@ -294,9 +273,6 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setSymbolsKeyboard"); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_setSymbolsKeyboard(); - } mSwitchActions.setSymbolsKeyboard(); mIsAlphabetMode = false; mIsSymbolShifted = false; @@ -309,9 +285,6 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setSymbolsShiftedKeyboard"); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_setSymbolsShiftedKeyboard(); - } mSwitchActions.setSymbolsShiftedKeyboard(); mIsAlphabetMode = false; mIsSymbolShifted = true; @@ -324,9 +297,6 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code) + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onPressKey(code, this); - } if (code == Keyboard.CODE_SHIFT) { onPressShift(); } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { @@ -344,9 +314,6 @@ public class KeyboardState { Log.d(TAG, "onReleaseKey: code=" + Keyboard.printableCode(code) + " sliding=" + withSliding + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onReleaseKey(this, code, withSliding); - } if (code == Keyboard.CODE_SHIFT) { onReleaseShift(withSliding); } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { @@ -378,9 +345,6 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onLongPressTimeout(code, this); - } if (mIsAlphabetMode && code == Keyboard.CODE_SHIFT) { if (mAlphabetShiftState.isShiftLocked()) { setShiftLocked(false); @@ -399,9 +363,6 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onUpdateShiftState(this, autoCaps); - } updateAlphabetShiftState(autoCaps); } @@ -520,9 +481,6 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onCancelInput: single=" + isSinglePointer + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onCancelInput(isSinglePointer, this); - } // Switch back to the previous keyboard mode if the user cancels sliding input. if (isSinglePointer) { if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) { @@ -554,9 +512,6 @@ public class KeyboardState { + " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onCodeInput(code, isSinglePointer, autoCaps, this); - } switch (mSwitchState) { case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java index 520177afe..38444a10c 100644 --- a/java/src/com/android/inputmethod/latin/AutoCorrection.java +++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java @@ -21,8 +21,6 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import android.text.TextUtils; import android.util.Log; -import com.android.inputmethod.latin.define.ProductionFlag; - import java.util.ArrayList; import java.util.HashMap; @@ -117,19 +115,10 @@ public class AutoCorrection { + autoCorrectionSuggestionScore + ", " + normalizedScore + "(" + autoCorrectionThreshold + ")"); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.autoCorrection_hasAutoCorrectionForBinaryDictionary(consideredWord, - autoCorrectionThreshold, autoCorrectionSuggestion.toString(), - autoCorrectionSuggestionScore, normalizedScore); - } if (normalizedScore >= autoCorrectionThreshold) { if (DBG) { Log.d(TAG, "Auto corrected by S-threshold."); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger - .autoCorrection_hasAutoCorrectionForBinaryDictionary_bySthreshold(); - } return true; } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index e0fa2f838..f5c09974e 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -665,9 +665,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen + String.format("inputType=0x%08x imeOptions=0x%08x", editorInfo.inputType, editorInfo.imeOptions)); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.latinIME_onStartInputViewInternal(editorInfo); - } if (StringUtils.inPrivateImeOptions(null, IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)) { Log.w(TAG, "Deprecated private IME option specified: " + editorInfo.privateImeOptions); @@ -765,6 +762,19 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, composingSpanEnd); + if (ProductionFlag.IS_EXPERIMENTAL) { + if (ResearchLogger.UnsLogGroup.ON_UPDATE_SELECTION.isEnabled) { + final String s = "onUpdateSelection: oss=" + oldSelStart + + ", ose=" + oldSelEnd + + ", lss=" + mLastSelectionStart + + ", lse=" + mLastSelectionEnd + + ", nss=" + newSelStart + + ", nse=" + newSelEnd + + ", cs=" + composingSpanStart + + ", ce=" + composingSpanEnd; + ResearchLogger.logUnstructured(ResearchLogger.UnsLogGroup.ON_UPDATE_SELECTION, s); + } + } if (DEBUG) { Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart + ", ose=" + oldSelEnd @@ -775,11 +785,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen + ", cs=" + composingSpanStart + ", ce=" + composingSpanEnd); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.latinIME_onUpdateSelection(mLastSelectionStart, mLastSelectionEnd, - oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, - composingSpanEnd); - } // TODO: refactor the following code to be less contrived. // "newSelStart != composingSpanEnd" || "newSelEnd != composingSpanEnd" means @@ -881,9 +886,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions); - } if (mInputAttributes.mApplicationSpecifiedCompletionOn) { mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; if (applicationSpecifiedCompletions == null) { @@ -1658,9 +1660,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (DEBUG) { Log.d(TAG, "Switch to keyboard view."); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.latinIME_switchToKeyboardView(); - } View v = mKeyboardSwitcher.getKeyboardView(); if (v != null) { // Confirms that the keyboard view doesn't have parent view. diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 182a7bc3e..c5fb61f78 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -25,20 +25,15 @@ import android.os.SystemClock; import android.text.TextUtils; import android.util.Log; import android.view.MotionEvent; -import android.view.inputmethod.CompletionInfo; -import android.view.inputmethod.EditorInfo; -import com.android.inputmethod.keyboard.Key; -import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.keyboard.internal.AlphabetShiftState; -import com.android.inputmethod.keyboard.internal.KeyboardState; -import com.android.inputmethod.latin.define.ProductionFlag; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Date; /** * Logs the use of the LatinIME keyboard. @@ -51,12 +46,13 @@ import java.io.PrintWriter; public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = ResearchLogger.class.getSimpleName(); private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; - private static final boolean DEBUG = false; private static final ResearchLogger sInstance = new ResearchLogger(new LogFileManager()); public static boolean sIsLogging = false; /* package */ final Handler mLoggingHandler; private InputMethodService mIms; + private final Date mDate; + private final SimpleDateFormat mDateFormat; /** * Isolates management of files. This variable should never be null, but can be changed @@ -83,36 +79,35 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang /* package */ LogFileManager() { } - public void init(final InputMethodService ims) { + public void init(InputMethodService ims) { mIms = ims; } - public synchronized boolean createLogFile() { + public synchronized void createLogFile() { try { - return createLogFile(DEFAULT_LOG_DIRECTORY, DEFAULT_FILENAME); - } catch (final FileNotFoundException e) { + createLogFile(DEFAULT_LOG_DIRECTORY, DEFAULT_FILENAME); + } catch (FileNotFoundException e) { Log.w(TAG, e); - return false; } } - public synchronized boolean createLogFile(final String dir, final String filename) + public synchronized void createLogFile(String dir, String filename) throws FileNotFoundException { if (mIms == null) { Log.w(TAG, "InputMethodService is not configured. Logging is off."); - return false; + return; } - final File filesDir = mIms.getFilesDir(); + File filesDir = mIms.getFilesDir(); if (filesDir == null || !filesDir.exists()) { Log.w(TAG, "Storage directory does not exist. Logging is off."); - return false; + return; } - final File directory = new File(filesDir, dir); + File directory = new File(filesDir, dir); if (!directory.exists()) { - final boolean wasCreated = directory.mkdirs(); + boolean wasCreated = directory.mkdirs(); if (!wasCreated) { Log.w(TAG, "Log directory cannot be created. Logging is off."); - return false; + return; } } @@ -125,23 +120,16 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang append = false; } mPrintWriter = new PrintWriter(new FileOutputStream(mFile, append), true); - return true; } - public synchronized boolean append(final String s) { + public synchronized boolean append(String s) { if (mPrintWriter == null) { - if (DEBUG) { - Log.w(TAG, "PrintWriter is null... attempting to create default log file"); - } - if (!createLogFile()) { - if (DEBUG) { - Log.w(TAG, "Failed to create log file. Not logging."); - return false; - } - } + Log.w(TAG, "PrintWriter is null"); + return false; + } else { + mPrintWriter.print(s); + return !mPrintWriter.checkError(); } - mPrintWriter.print(s); - return !mPrintWriter.checkError(); } public synchronized void reset() { @@ -164,8 +152,11 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - private ResearchLogger(final LogFileManager logFileManager) { - final HandlerThread handlerThread = new HandlerThread("ResearchLogger logging task", + private ResearchLogger(LogFileManager logFileManager) { + mDate = new Date(); + mDateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss.SSSZ"); + + HandlerThread handlerThread = new HandlerThread("ResearchLogger logging task", Process.THREAD_PRIORITY_BACKGROUND); handlerThread.start(); mLoggingHandler = new Handler(handlerThread.getLooper()); @@ -176,11 +167,11 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang return sInstance; } - public static void init(final InputMethodService ims, final SharedPreferences prefs) { + public static void init(InputMethodService ims, SharedPreferences prefs) { sInstance.initInternal(ims, prefs); } - public void initInternal(final InputMethodService ims, final SharedPreferences prefs) { + public void initInternal(InputMethodService ims, SharedPreferences prefs) { mIms = ims; if (mLogFileManager != null) { mLogFileManager.init(ims); @@ -197,7 +188,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang * * @throws IllegalArgumentException if logFileManager is null */ - void setLogFileManager(final LogFileManager manager) { + void setLogFileManager(LogFileManager manager) { if (manager == null) { throw new IllegalArgumentException("warning: trying to set null logFileManager"); } else { @@ -212,12 +203,11 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang MOTION_EVENT("m"), KEY("k"), CORRECTION("c"), - STATE_CHANGE("s"), - UNSTRUCTURED("u"); + STATE_CHANGE("s"); private final String mLogString; - private LogGroup(final String logString) { + private LogGroup(String logString) { mLogString = logString; } } @@ -236,7 +226,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang default: eventTag = "[Action" + action + "]"; break; } if (!TextUtils.isEmpty(eventTag)) { - final StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(); sb.append(eventTag); sb.append('\t'); sb.append(eventTime); sb.append('\t'); sb.append(id); @@ -248,7 +238,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - public void logKeyEvent(final int code, final int x, final int y) { + public void logKeyEvent(int code, int x, int y) { final StringBuilder sb = new StringBuilder(); sb.append(Keyboard.printableCode(code)); sb.append('\t'); sb.append(x); @@ -256,8 +246,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang write(LogGroup.KEY, sb.toString()); } - public void logCorrection(final String subgroup, final String before, final String after, - final int position) { + public void logCorrection(String subgroup, String before, String after, int position) { final StringBuilder sb = new StringBuilder(); sb.append(subgroup); sb.append('\t'); sb.append(before); @@ -266,62 +255,19 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang write(LogGroup.CORRECTION, sb.toString()); } - public void logStateChange(final String subgroup, final String details) { + public void logStateChange(String subgroup, String details) { write(LogGroup.STATE_CHANGE, subgroup + "\t" + details); } - public static class UnsLogGroup { - private static final boolean DEFAULT_ENABLED = true; - - private static final boolean ALPHABETSHIFTSTATE_SETSHIFTED_ENABLED = DEFAULT_ENABLED; - private static final boolean ALPHABETSHIFTSTATE_SETSHIFTLOCKED_ENABLED = DEFAULT_ENABLED; - private static final boolean ALPHABETSHIFTSTATE_SETAUTOMATICSHIFTED_ENABLED - = DEFAULT_ENABLED; - private static final boolean AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_ENABLED - = DEFAULT_ENABLED; - private static final boolean - AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_BYSTHRESHOLD_ENABLED - = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_ONCANCELINPUT_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_ONCODEINPUT_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_ONPRESSKEY_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_ONRELEASEKEY_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_ONRESTOREKEYBOARDSTATE_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_ONSAVEKEYBOARDSTATE_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_ONUPDATESHIFTSTATE_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_SETALPHABETKEYBOARD_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_SETSHIFTED_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_SETSHIFTLOCKED_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_SETSYMBOLSKEYBOARD_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_SETSYMBOLSSHIFTEDKEYBOARD_ENABLED - = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED - = DEFAULT_ENABLED; - private static final boolean LATINIME_ONDISPLAYCOMPLETIONS_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_ONUPDATESELECTION_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED - = DEFAULT_ENABLED; - private static final boolean POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED - = DEFAULT_ENABLED; - private static final boolean POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED - = DEFAULT_ENABLED; - private static final boolean - POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED - = DEFAULT_ENABLED; - private static final boolean POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED = DEFAULT_ENABLED; - private static final boolean POINTERTRACKER_ONDOWNEVENT_ENABLED = DEFAULT_ENABLED; - private static final boolean POINTERTRACKER_ONMOVEEVENT_ENABLED = DEFAULT_ENABLED; - private static final boolean SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED - = DEFAULT_ENABLED; + public static enum UnsLogGroup { + // TODO: expand to include one flag per log point + // TODO: support selective enabling of flags + ON_UPDATE_SELECTION; + + public boolean isEnabled = true; } - public static void logUnstructured(String logGroup, final String details) { - // TODO: improve performance by making entire class static and/or implementing natively - getInstance().write(LogGroup.UNSTRUCTURED, logGroup + "\t" + details); + public static void logUnstructured(UnsLogGroup logGroup, String details) { } private void write(final LogGroup logGroup, final String log) { @@ -336,14 +282,13 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang builder.append('\t'); builder.append(upTime); builder.append('\t'); builder.append(logGroup.mLogString); builder.append('\t'); builder.append(log); - builder.append('\n'); - if (DEBUG) { + if (LatinImeLogger.sDBG) { Log.d(TAG, "Write: " + '[' + logGroup.mLogString + ']' + log); } if (mLogFileManager.append(builder.toString())) { // success } else { - if (DEBUG) { + if (LatinImeLogger.sDBG) { Log.w(TAG, "Unable to write to log."); } } @@ -355,7 +300,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mLoggingHandler.post(new Runnable() { @Override public void run() { - if (DEBUG) { + if (LatinImeLogger.sDBG) { Log.d(TAG, "Delete log file."); } mLogFileManager.reset(); @@ -370,300 +315,4 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); } - - public static void alphabetShiftState_setShifted(final boolean newShiftState, - final int oldState, final AlphabetShiftState alphabetShiftState) { - if (UnsLogGroup.ALPHABETSHIFTSTATE_SETSHIFTED_ENABLED) { - final String s = "setShifted(" + newShiftState + "): " + oldState - + " > " + alphabetShiftState; - logUnstructured("AlphabetShiftState_setShifted", s); - } - } - - public static void alphabetShiftState_setShiftLocked(final boolean newShiftLockState, - final int oldState, final AlphabetShiftState alphabetShiftState) { - if (UnsLogGroup.ALPHABETSHIFTSTATE_SETSHIFTLOCKED_ENABLED) { - final String s = "setShiftLocked(" + newShiftLockState + "): " - + oldState + " > " + alphabetShiftState; - logUnstructured("AlphabetShiftState_setShiftLocked", s); - } - } - - public static void alphabetShiftState_setAutomaticShifted(final int oldState, - final AlphabetShiftState alphabetShiftState) { - if (UnsLogGroup.ALPHABETSHIFTSTATE_SETAUTOMATICSHIFTED_ENABLED) { - final String s = "setAutomaticShifted: " + oldState + " > " + alphabetShiftState; - logUnstructured("AlphabetShiftState_setAutomaticShifted", s); - } - } - - public static void autoCorrection_hasAutoCorrectionForBinaryDictionary( - final CharSequence consideredWord, final double autoCorrectionThreshold, - final CharSequence autoCorrectionSuggestion, final int autoCorrectionSuggestionScore, - final double normalizedScore) { - if (UnsLogGroup.AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_ENABLED) { - final String s = "Normalized " + consideredWord + "," - + autoCorrectionSuggestion + "," + autoCorrectionSuggestionScore - + ", " + normalizedScore + "(" + autoCorrectionThreshold + ")"; - logUnstructured("AutoCorrection_hasAutoCorrectionForBinaryDictionary", s); - } - } - - public static void autoCorrection_hasAutoCorrectionForBinaryDictionary_bySthreshold() { - if (UnsLogGroup.AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_BYSTHRESHOLD_ENABLED) { - final String s = "Auto corrected by S-threshold."; - logUnstructured("AutoCorrection_hasAutoCorrectionForBinaryDictionar_bySthreshold", s); - } - } - - public static void keyboardState_onCancelInput(final boolean isSinglePointer, - final KeyboardState keyboardState) { - if (UnsLogGroup.KEYBOARDSTATE_ONCANCELINPUT_ENABLED) { - final String s = "onCancelInput: single=" + isSinglePointer + " " + keyboardState; - logUnstructured("KeyboardState_onCancelInput", s); - } - } - - public static void keyboardState_onCodeInput( - final int code, final boolean isSinglePointer, final boolean autoCaps, - final KeyboardState keyboardState) { - if (UnsLogGroup.KEYBOARDSTATE_ONCODEINPUT_ENABLED) { - final String s = "onCodeInput: code=" + Keyboard.printableCode(code) - + " single=" + isSinglePointer - + " autoCaps=" + autoCaps + " " + keyboardState; - logUnstructured("KeyboardState_onCodeInput", s); - } - } - - public static void keyboardState_onLongPressTimeout(final int code, - final KeyboardState keyboardState) { - if (UnsLogGroup.KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED) { - final String s = "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " - + keyboardState; - logUnstructured("KeyboardState_onLongPressTimeout", s); - } - } - - public static void keyboardState_onPressKey(final int code, - final KeyboardState keyboardState) { - if (UnsLogGroup.KEYBOARDSTATE_ONPRESSKEY_ENABLED) { - final String s = "onPressKey: code=" + Keyboard.printableCode(code) + " " - + keyboardState; - logUnstructured("KeyboardState_onPressKey", s); - } - } - - public static void keyboardState_onReleaseKey(final KeyboardState keyboardState, final int code, - final boolean withSliding) { - if (UnsLogGroup.KEYBOARDSTATE_ONRELEASEKEY_ENABLED) { - final String s = "onReleaseKey: code=" + Keyboard.printableCode(code) - + " sliding=" + withSliding + " " + keyboardState; - logUnstructured("KeyboardState_onReleaseKey", s); - } - } - - public static void keyboardState_onRestoreKeyboardState(final KeyboardState keyboardState, - final String savedKeyboardState) { - if (UnsLogGroup.KEYBOARDSTATE_ONRESTOREKEYBOARDSTATE_ENABLED) { - final String s = "onRestoreKeyboardState: saved=" + savedKeyboardState + " " - + keyboardState; - logUnstructured("KeyboardState_onRestoreKeyboardState", s); - } - } - - public static void keyboardState_onSaveKeyboardState(final KeyboardState keyboardState, - final String savedKeyboardState) { - if (UnsLogGroup.KEYBOARDSTATE_ONSAVEKEYBOARDSTATE_ENABLED) { - final String s = "onSaveKeyboardState: saved=" + savedKeyboardState + " " - + keyboardState; - logUnstructured("KeyboardState_onSaveKeyboardState", s); - } - } - - public static void keyboardState_onUpdateShiftState(final KeyboardState keyboardState, - final boolean autoCaps) { - if (UnsLogGroup.KEYBOARDSTATE_ONUPDATESHIFTSTATE_ENABLED) { - final String s = "onUpdateShiftState: autoCaps=" + autoCaps + " " + keyboardState; - logUnstructured("KeyboardState_onUpdateShiftState", s); - } - } - - public static void keyboardState_setAlphabetKeyboard() { - if (UnsLogGroup.KEYBOARDSTATE_SETALPHABETKEYBOARD_ENABLED) { - final String s = "setAlphabetKeyboard"; - logUnstructured("KeyboardState_setAlphabetKeyboard", s); - } - } - - public static void keyboardState_setShifted(final KeyboardState keyboardState, - final String shiftMode) { - if (UnsLogGroup.KEYBOARDSTATE_SETSHIFTED_ENABLED) { - final String s = "setShifted: shiftMode=" + shiftMode + " " + keyboardState; - logUnstructured("KeyboardState_setShifted", s); - } - } - - public static void keyboardState_setShiftLocked(final KeyboardState keyboardState, - final boolean shiftLocked) { - if (UnsLogGroup.KEYBOARDSTATE_SETSHIFTLOCKED_ENABLED) { - final String s = "setShiftLocked: shiftLocked=" + shiftLocked + " " + keyboardState; - logUnstructured("KeyboardState_setShiftLocked", s); - } - } - - public static void keyboardState_setSymbolsKeyboard() { - if (UnsLogGroup.KEYBOARDSTATE_SETSYMBOLSKEYBOARD_ENABLED) { - final String s = "setSymbolsKeyboard"; - logUnstructured("KeyboardState_setSymbolsKeyboard", s); - } - } - - public static void keyboardState_setSymbolsShiftedKeyboard() { - if (UnsLogGroup.KEYBOARDSTATE_SETSYMBOLSSHIFTEDKEYBOARD_ENABLED) { - final String s = "setSymbolsShiftedKeyboard"; - logUnstructured("KeyboardState_setSymbolsShiftedKeyboard", s); - } - } - - public static void keyboardState_toggleAlphabetAndSymbols(final KeyboardState keyboardState) { - if (UnsLogGroup.KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED) { - final String s = "toggleAlphabetAndSymbols: " + keyboardState; - logUnstructured("KeyboardState_toggleAlphabetAndSymbols", s); - } - } - - public static void latinIME_onDisplayCompletions( - final CompletionInfo[] applicationSpecifiedCompletions) { - if (UnsLogGroup.LATINIME_ONDISPLAYCOMPLETIONS_ENABLED) { - final StringBuilder builder = new StringBuilder(); - builder.append("Received completions:"); - if (applicationSpecifiedCompletions != null) { - for (int i = 0; i < applicationSpecifiedCompletions.length; i++) { - builder.append(" #"); - builder.append(i); - builder.append(": "); - builder.append(applicationSpecifiedCompletions[i]); - builder.append("\n"); - } - } - logUnstructured("LatinIME_onDisplayCompletions", builder.toString()); - } - } - - public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo) { - if (UnsLogGroup.LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED) { - final StringBuilder builder = new StringBuilder(); - builder.append("onStartInputView: editorInfo:"); - builder.append("inputType="); - builder.append(editorInfo.inputType); - builder.append("imeOptions="); - builder.append(editorInfo.imeOptions); - logUnstructured("LatinIME_onStartInputViewInternal", builder.toString()); - } - } - - public static void latinIME_onUpdateSelection(final int lastSelectionStart, - final int lastSelectionEnd, final int oldSelStart, final int oldSelEnd, - final int newSelStart, final int newSelEnd, final int composingSpanStart, - final int composingSpanEnd) { - if (UnsLogGroup.LATINIME_ONUPDATESELECTION_ENABLED) { - final String s = "onUpdateSelection: oss=" + oldSelStart - + ", ose=" + oldSelEnd - + ", lss=" + lastSelectionStart - + ", lse=" + lastSelectionEnd - + ", nss=" + newSelStart - + ", nse=" + newSelEnd - + ", cs=" + composingSpanStart - + ", ce=" + composingSpanEnd; - logUnstructured("LatinIME_onUpdateSelection", s); - } - } - - public static void latinIME_switchToKeyboardView() { - if (UnsLogGroup.LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED) { - final String s = "Switch to keyboard view."; - logUnstructured("LatinIME_switchToKeyboardView", s); - } - } - - public static void latinKeyboardView_onLongPress() { - if (UnsLogGroup.LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED) { - final String s = "long press detected"; - logUnstructured("LatinKeyboardView_onLongPress", s); - } - } - - public static void latinKeyboardView_processMotionEvent(MotionEvent me, int action, - long eventTime, int index, int id, int x, int y) { - if (UnsLogGroup.LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED) { - final float size = me.getSize(index); - final float pressure = me.getPressure(index); - if (action != MotionEvent.ACTION_MOVE) { - getInstance().logMotionEvent(action, eventTime, id, x, y, size, pressure); - } - } - } - - public static void pointerTracker_callListenerOnCancelInput() { - final String s = "onCancelInput"; - if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED) { - logUnstructured("PointerTracker_callListenerOnCancelInput", s); - } - } - - public static void pointerTracker_callListenerOnCodeInput(final Key key, final int x, - final int y, final boolean ignoreModifierKey, final boolean altersCode, - final int code) { - if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED) { - final String s = "onCodeInput: " + Keyboard.printableCode(code) - + " text=" + key.mOutputText + " x=" + x + " y=" + y - + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode - + " enabled=" + key.isEnabled(); - logUnstructured("PointerTracker_callListenerOnCodeInput", s); - } - } - - public static void pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange( - final Key key, final boolean ignoreModifierKey) { - if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED) { - final String s = "onPress : " + KeyDetector.printableCode(key) - + " ignoreModifier=" + ignoreModifierKey - + " enabled=" + key.isEnabled(); - logUnstructured("PointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange", s); - } - } - - public static void pointerTracker_callListenerOnRelease(final Key key, final int primaryCode, - final boolean withSliding, final boolean ignoreModifierKey) { - if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED) { - final String s = "onRelease : " + Keyboard.printableCode(primaryCode) - + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey - + " enabled="+ key.isEnabled(); - logUnstructured("PointerTracker_callListenerOnRelease", s); - } - } - - public static void pointerTracker_onDownEvent(long deltaT, int distanceSquared) { - if (UnsLogGroup.POINTERTRACKER_ONDOWNEVENT_ENABLED) { - final String s = "onDownEvent: ignore potential noise: time=" + deltaT - + " distance=" + distanceSquared; - logUnstructured("PointerTracker_onDownEvent", s); - } - } - - public static void pointerTracker_onMoveEvent(final int x, final int y, final int lastX, - final int lastY) { - if (UnsLogGroup.POINTERTRACKER_ONMOVEEVENT_ENABLED) { - final String s = String.format("onMoveEvent: sudden move is translated to " - + "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y); - logUnstructured("PointerTracker_onMoveEvent", s); - } - } - - public static void suddenJumpingTouchEventHandler_onTouchEvent(final MotionEvent me) { - if (UnsLogGroup.SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED) { - final String s = "onTouchEvent: ignore sudden jump " + me; - logUnstructured("SuddenJumpingTouchEventHandler_onTouchEvent", s); - } - } } -- cgit v1.2.3-83-g751a From 9bc29d78a6ce83f77869aa63748176241e29d43c Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Fri, 30 Mar 2012 13:15:46 -0700 Subject: add more data collection points to ResearchLogger (attempt #2) the new points are all at Log.x() positions; only those appearing directly related to user input were added. multi-project change with I159f5de2 this CL is the same as I618bcd07, which was reverted because of incompatibilities with vendor branches. Bug: 6188932 Change-Id: I999249dceb0c04f5a4ffbfff25caed09d24a2c52 --- .../inputmethod/keyboard/LatinKeyboardView.java | 25 +- .../inputmethod/keyboard/PointerTracker.java | 23 ++ .../keyboard/SuddenJumpingTouchEventHandler.java | 5 + .../keyboard/internal/AlphabetShiftState.java | 12 + .../keyboard/internal/KeyboardState.java | 45 +++ .../android/inputmethod/latin/AutoCorrection.java | 11 + .../com/android/inputmethod/latin/LatinIME.java | 27 +- .../android/inputmethod/latin/ResearchLogger.java | 441 ++++++++++++++++++--- 8 files changed, 513 insertions(+), 76 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 2689e6e13..98da1eb65 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -555,6 +555,9 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke * method on the base class if the subclass doesn't wish to handle the call. */ protected boolean onLongPress(Key parentKey, PointerTracker tracker) { + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinKeyboardView_onLongPress(); + } final int primaryCode = parentKey.mCode; if (parentKey.hasEmbeddedMoreKey()) { final int embeddedCode = KeySpecParser.getCode(getResources(), parentKey.mMoreKeys[0]); @@ -695,17 +698,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } } if (ProductionFlag.IS_EXPERIMENTAL) { - if (ResearchLogger.sIsLogging) { - // TODO: remove redundant calculations of size and pressure by - // removing UsabilityStudyLog code once the ResearchLogger is mature enough - final float size = me.getSize(index); - final float pressure = me.getPressure(index); - if (action != MotionEvent.ACTION_MOVE) { - // Skip ACTION_MOVE events as they are logged below - ResearchLogger.getInstance().logMotionEvent(action, eventTime, id, x, y, - size, pressure); - } - } + ResearchLogger.latinKeyboardView_processMotionEvent(me, action, eventTime, index, id, + x, y); } if (mKeyTimerHandler.isInKeyRepeat()) { @@ -773,13 +767,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke + pointerSize + "," + pointerPressure); } if (ProductionFlag.IS_EXPERIMENTAL) { - if (ResearchLogger.sIsLogging) { - // TODO: earlier comment about redundant calculations applies here too - final float pointerSize = me.getSize(i); - final float pointerPressure = me.getPressure(i); - ResearchLogger.getInstance().logMotionEvent(action, eventTime, pointerId, - px, py, pointerSize, pointerPressure); - } + ResearchLogger.latinKeyboardView_processMotionEvent(me, action, eventTime, + i, pointerId, px, py); } } } else { diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index ec9081681..24ab54730 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -23,6 +23,8 @@ import android.widget.TextView; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.ResearchLogger; +import com.android.inputmethod.latin.define.ProductionFlag; import java.util.ArrayList; @@ -235,6 +237,10 @@ public class PointerTracker { + " ignoreModifier=" + ignoreModifierKey + " enabled=" + key.isEnabled()); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange(key, + ignoreModifierKey); + } if (ignoreModifierKey) { return false; } @@ -259,6 +265,10 @@ public class PointerTracker { + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode + " enabled=" + key.isEnabled()); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_callListenerOnCodeInput(key, x, y, ignoreModifierKey, + altersCode, code); + } if (ignoreModifierKey) { return; } @@ -284,6 +294,10 @@ public class PointerTracker { + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey + " enabled="+ key.isEnabled()); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_callListenerOnRelease(key, primaryCode, withSliding, + ignoreModifierKey); + } if (ignoreModifierKey) { return; } @@ -295,6 +309,9 @@ public class PointerTracker { private void callListenerOnCancelInput() { if (DEBUG_LISTENER) Log.d(TAG, "onCancelInput"); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_callListenerOnCancelInput(); + } mListener.onCancelInput(); } @@ -479,6 +496,9 @@ public class PointerTracker { if (DEBUG_MODE) Log.w(TAG, "onDownEvent: ignore potential noise: time=" + deltaT + " distance=" + distanceSquared); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_onDownEvent(deltaT, distanceSquared); + } mKeyAlreadyProcessed = true; return; } @@ -583,6 +603,9 @@ public class PointerTracker { if (DEBUG_MODE) Log.w(TAG, String.format("onMoveEvent: sudden move is translated to " + "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y)); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_onMoveEvent(x, y, lastX, lastY); + } onUpEventInternal(lastX, lastY, eventTime); onDownEventInternal(x, y, eventTime); } else { diff --git a/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java b/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java index 347383f95..107138395 100644 --- a/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java +++ b/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java @@ -22,7 +22,9 @@ import android.view.MotionEvent; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.ResearchLogger; import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.define.ProductionFlag; public class SuddenJumpingTouchEventHandler { private static final String TAG = SuddenJumpingTouchEventHandler.class.getSimpleName(); @@ -141,6 +143,9 @@ public class SuddenJumpingTouchEventHandler { if (handleSuddenJumping(me)) { if (DEBUG_MODE) Log.w(TAG, "onTouchEvent: ignore sudden jump " + me); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.suddenJumpingTouchEventHandler_onTouchEvent(me); + } return true; } return mView.processMotionEvent(me); diff --git a/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java index 5712df1fc..392afca97 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java @@ -18,6 +18,9 @@ package com.android.inputmethod.keyboard.internal; import android.util.Log; +import com.android.inputmethod.latin.ResearchLogger; +import com.android.inputmethod.latin.define.ProductionFlag; + public class AlphabetShiftState { private static final String TAG = AlphabetShiftState.class.getSimpleName(); private static final boolean DEBUG = false; @@ -59,6 +62,9 @@ public class AlphabetShiftState { } if (DEBUG) Log.d(TAG, "setShifted(" + newShiftState + "): " + toString(oldState) + " > " + this); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.alphabetShiftState_setShifted(newShiftState, oldState, this); + } } public void setShiftLocked(boolean newShiftLockState) { @@ -78,6 +84,9 @@ public class AlphabetShiftState { if (DEBUG) Log.d(TAG, "setShiftLocked(" + newShiftLockState + "): " + toString(oldState) + " > " + this); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.alphabetShiftState_setShiftLocked(newShiftLockState, oldState, this); + } } public void setAutomaticShifted() { @@ -85,6 +94,9 @@ public class AlphabetShiftState { mState = AUTOMATIC_SHIFTED; if (DEBUG) Log.d(TAG, "setAutomaticShifted: " + toString(oldState) + " > " + this); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.alphabetShiftState_setAutomaticShifted(oldState, this); + } } public boolean isShiftedOrShiftLocked() { diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index 18a3f9794..6949c9d12 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -20,6 +20,8 @@ import android.text.TextUtils; import android.util.Log; import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.latin.ResearchLogger; +import com.android.inputmethod.latin.define.ProductionFlag; /** * Keyboard state machine. @@ -139,6 +141,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onSaveKeyboardState: saved=" + state + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onSaveKeyboardState(this, state.toString()); + } } private void onRestoreKeyboardState() { @@ -146,6 +151,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onRestoreKeyboardState: saved=" + state + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onRestoreKeyboardState(this, state.toString()); + } if (!state.mIsValid || state.mIsAlphabetMode) { setAlphabetKeyboard(); } else { @@ -178,6 +186,9 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode) + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_setShifted(this, shiftModeToString(shiftMode)); + } if (!mIsAlphabetMode) return; final int prevShiftMode; if (mAlphabetShiftState.isAutomaticShifted()) { @@ -217,6 +228,9 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setShiftLocked: shiftLocked=" + shiftLocked + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_setShiftLocked(this, shiftLocked); + } if (!mIsAlphabetMode) return; if (shiftLocked && (!mAlphabetShiftState.isShiftLocked() || mAlphabetShiftState.isShiftLockShifted())) { @@ -232,6 +246,9 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "toggleAlphabetAndSymbols: " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_toggleAlphabetAndSymbols(this); + } if (mIsAlphabetMode) { mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked(); if (mPrevSymbolsKeyboardWasShifted) { @@ -262,6 +279,10 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setAlphabetKeyboard"); } + + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_setAlphabetKeyboard(); + } mSwitchActions.setAlphabetKeyboard(); mIsAlphabetMode = true; mIsSymbolShifted = false; @@ -273,6 +294,9 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setSymbolsKeyboard"); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_setSymbolsKeyboard(); + } mSwitchActions.setSymbolsKeyboard(); mIsAlphabetMode = false; mIsSymbolShifted = false; @@ -285,6 +309,9 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setSymbolsShiftedKeyboard"); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_setSymbolsShiftedKeyboard(); + } mSwitchActions.setSymbolsShiftedKeyboard(); mIsAlphabetMode = false; mIsSymbolShifted = true; @@ -297,6 +324,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code) + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onPressKey(code, this); + } if (code == Keyboard.CODE_SHIFT) { onPressShift(); } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { @@ -314,6 +344,9 @@ public class KeyboardState { Log.d(TAG, "onReleaseKey: code=" + Keyboard.printableCode(code) + " sliding=" + withSliding + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onReleaseKey(this, code, withSliding); + } if (code == Keyboard.CODE_SHIFT) { onReleaseShift(withSliding); } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { @@ -345,6 +378,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onLongPressTimeout(code, this); + } if (mIsAlphabetMode && code == Keyboard.CODE_SHIFT) { if (mAlphabetShiftState.isShiftLocked()) { setShiftLocked(false); @@ -363,6 +399,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onUpdateShiftState(this, autoCaps); + } updateAlphabetShiftState(autoCaps); } @@ -481,6 +520,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onCancelInput: single=" + isSinglePointer + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onCancelInput(isSinglePointer, this); + } // Switch back to the previous keyboard mode if the user cancels sliding input. if (isSinglePointer) { if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) { @@ -512,6 +554,9 @@ public class KeyboardState { + " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onCodeInput(code, isSinglePointer, autoCaps, this); + } switch (mSwitchState) { case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java index 38444a10c..520177afe 100644 --- a/java/src/com/android/inputmethod/latin/AutoCorrection.java +++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java @@ -21,6 +21,8 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import android.text.TextUtils; import android.util.Log; +import com.android.inputmethod.latin.define.ProductionFlag; + import java.util.ArrayList; import java.util.HashMap; @@ -115,10 +117,19 @@ public class AutoCorrection { + autoCorrectionSuggestionScore + ", " + normalizedScore + "(" + autoCorrectionThreshold + ")"); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.autoCorrection_hasAutoCorrectionForBinaryDictionary(consideredWord, + autoCorrectionThreshold, autoCorrectionSuggestion.toString(), + autoCorrectionSuggestionScore, normalizedScore); + } if (normalizedScore >= autoCorrectionThreshold) { if (DBG) { Log.d(TAG, "Auto corrected by S-threshold."); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger + .autoCorrection_hasAutoCorrectionForBinaryDictionary_bySthreshold(); + } return true; } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index f5c09974e..e0fa2f838 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -665,6 +665,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen + String.format("inputType=0x%08x imeOptions=0x%08x", editorInfo.inputType, editorInfo.imeOptions)); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_onStartInputViewInternal(editorInfo); + } if (StringUtils.inPrivateImeOptions(null, IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)) { Log.w(TAG, "Deprecated private IME option specified: " + editorInfo.privateImeOptions); @@ -762,19 +765,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, composingSpanEnd); - if (ProductionFlag.IS_EXPERIMENTAL) { - if (ResearchLogger.UnsLogGroup.ON_UPDATE_SELECTION.isEnabled) { - final String s = "onUpdateSelection: oss=" + oldSelStart - + ", ose=" + oldSelEnd - + ", lss=" + mLastSelectionStart - + ", lse=" + mLastSelectionEnd - + ", nss=" + newSelStart - + ", nse=" + newSelEnd - + ", cs=" + composingSpanStart - + ", ce=" + composingSpanEnd; - ResearchLogger.logUnstructured(ResearchLogger.UnsLogGroup.ON_UPDATE_SELECTION, s); - } - } if (DEBUG) { Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart + ", ose=" + oldSelEnd @@ -785,6 +775,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen + ", cs=" + composingSpanStart + ", ce=" + composingSpanEnd); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_onUpdateSelection(mLastSelectionStart, mLastSelectionEnd, + oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, + composingSpanEnd); + } // TODO: refactor the following code to be less contrived. // "newSelStart != composingSpanEnd" || "newSelEnd != composingSpanEnd" means @@ -886,6 +881,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions); + } if (mInputAttributes.mApplicationSpecifiedCompletionOn) { mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; if (applicationSpecifiedCompletions == null) { @@ -1660,6 +1658,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (DEBUG) { Log.d(TAG, "Switch to keyboard view."); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_switchToKeyboardView(); + } View v = mKeyboardSwitcher.getKeyboardView(); if (v != null) { // Confirms that the keyboard view doesn't have parent view. diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index c5fb61f78..182a7bc3e 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -25,15 +25,20 @@ import android.os.SystemClock; import android.text.TextUtils; import android.util.Log; import android.view.MotionEvent; +import android.view.inputmethod.CompletionInfo; +import android.view.inputmethod.EditorInfo; +import com.android.inputmethod.keyboard.Key; +import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.keyboard.internal.AlphabetShiftState; +import com.android.inputmethod.keyboard.internal.KeyboardState; +import com.android.inputmethod.latin.define.ProductionFlag; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintWriter; -import java.text.SimpleDateFormat; -import java.util.Date; /** * Logs the use of the LatinIME keyboard. @@ -46,13 +51,12 @@ import java.util.Date; public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = ResearchLogger.class.getSimpleName(); private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; + private static final boolean DEBUG = false; private static final ResearchLogger sInstance = new ResearchLogger(new LogFileManager()); public static boolean sIsLogging = false; /* package */ final Handler mLoggingHandler; private InputMethodService mIms; - private final Date mDate; - private final SimpleDateFormat mDateFormat; /** * Isolates management of files. This variable should never be null, but can be changed @@ -79,35 +83,36 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang /* package */ LogFileManager() { } - public void init(InputMethodService ims) { + public void init(final InputMethodService ims) { mIms = ims; } - public synchronized void createLogFile() { + public synchronized boolean createLogFile() { try { - createLogFile(DEFAULT_LOG_DIRECTORY, DEFAULT_FILENAME); - } catch (FileNotFoundException e) { + return createLogFile(DEFAULT_LOG_DIRECTORY, DEFAULT_FILENAME); + } catch (final FileNotFoundException e) { Log.w(TAG, e); + return false; } } - public synchronized void createLogFile(String dir, String filename) + public synchronized boolean createLogFile(final String dir, final String filename) throws FileNotFoundException { if (mIms == null) { Log.w(TAG, "InputMethodService is not configured. Logging is off."); - return; + return false; } - File filesDir = mIms.getFilesDir(); + final File filesDir = mIms.getFilesDir(); if (filesDir == null || !filesDir.exists()) { Log.w(TAG, "Storage directory does not exist. Logging is off."); - return; + return false; } - File directory = new File(filesDir, dir); + final File directory = new File(filesDir, dir); if (!directory.exists()) { - boolean wasCreated = directory.mkdirs(); + final boolean wasCreated = directory.mkdirs(); if (!wasCreated) { Log.w(TAG, "Log directory cannot be created. Logging is off."); - return; + return false; } } @@ -120,16 +125,23 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang append = false; } mPrintWriter = new PrintWriter(new FileOutputStream(mFile, append), true); + return true; } - public synchronized boolean append(String s) { + public synchronized boolean append(final String s) { if (mPrintWriter == null) { - Log.w(TAG, "PrintWriter is null"); - return false; - } else { - mPrintWriter.print(s); - return !mPrintWriter.checkError(); + if (DEBUG) { + Log.w(TAG, "PrintWriter is null... attempting to create default log file"); + } + if (!createLogFile()) { + if (DEBUG) { + Log.w(TAG, "Failed to create log file. Not logging."); + return false; + } + } } + mPrintWriter.print(s); + return !mPrintWriter.checkError(); } public synchronized void reset() { @@ -152,11 +164,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - private ResearchLogger(LogFileManager logFileManager) { - mDate = new Date(); - mDateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss.SSSZ"); - - HandlerThread handlerThread = new HandlerThread("ResearchLogger logging task", + private ResearchLogger(final LogFileManager logFileManager) { + final HandlerThread handlerThread = new HandlerThread("ResearchLogger logging task", Process.THREAD_PRIORITY_BACKGROUND); handlerThread.start(); mLoggingHandler = new Handler(handlerThread.getLooper()); @@ -167,11 +176,11 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang return sInstance; } - public static void init(InputMethodService ims, SharedPreferences prefs) { + public static void init(final InputMethodService ims, final SharedPreferences prefs) { sInstance.initInternal(ims, prefs); } - public void initInternal(InputMethodService ims, SharedPreferences prefs) { + public void initInternal(final InputMethodService ims, final SharedPreferences prefs) { mIms = ims; if (mLogFileManager != null) { mLogFileManager.init(ims); @@ -188,7 +197,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang * * @throws IllegalArgumentException if logFileManager is null */ - void setLogFileManager(LogFileManager manager) { + void setLogFileManager(final LogFileManager manager) { if (manager == null) { throw new IllegalArgumentException("warning: trying to set null logFileManager"); } else { @@ -203,11 +212,12 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang MOTION_EVENT("m"), KEY("k"), CORRECTION("c"), - STATE_CHANGE("s"); + STATE_CHANGE("s"), + UNSTRUCTURED("u"); private final String mLogString; - private LogGroup(String logString) { + private LogGroup(final String logString) { mLogString = logString; } } @@ -226,7 +236,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang default: eventTag = "[Action" + action + "]"; break; } if (!TextUtils.isEmpty(eventTag)) { - StringBuilder sb = new StringBuilder(); + final StringBuilder sb = new StringBuilder(); sb.append(eventTag); sb.append('\t'); sb.append(eventTime); sb.append('\t'); sb.append(id); @@ -238,7 +248,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - public void logKeyEvent(int code, int x, int y) { + public void logKeyEvent(final int code, final int x, final int y) { final StringBuilder sb = new StringBuilder(); sb.append(Keyboard.printableCode(code)); sb.append('\t'); sb.append(x); @@ -246,7 +256,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang write(LogGroup.KEY, sb.toString()); } - public void logCorrection(String subgroup, String before, String after, int position) { + public void logCorrection(final String subgroup, final String before, final String after, + final int position) { final StringBuilder sb = new StringBuilder(); sb.append(subgroup); sb.append('\t'); sb.append(before); @@ -255,19 +266,62 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang write(LogGroup.CORRECTION, sb.toString()); } - public void logStateChange(String subgroup, String details) { + public void logStateChange(final String subgroup, final String details) { write(LogGroup.STATE_CHANGE, subgroup + "\t" + details); } - public static enum UnsLogGroup { - // TODO: expand to include one flag per log point - // TODO: support selective enabling of flags - ON_UPDATE_SELECTION; - - public boolean isEnabled = true; + public static class UnsLogGroup { + private static final boolean DEFAULT_ENABLED = true; + + private static final boolean ALPHABETSHIFTSTATE_SETSHIFTED_ENABLED = DEFAULT_ENABLED; + private static final boolean ALPHABETSHIFTSTATE_SETSHIFTLOCKED_ENABLED = DEFAULT_ENABLED; + private static final boolean ALPHABETSHIFTSTATE_SETAUTOMATICSHIFTED_ENABLED + = DEFAULT_ENABLED; + private static final boolean AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_ENABLED + = DEFAULT_ENABLED; + private static final boolean + AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_BYSTHRESHOLD_ENABLED + = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONCANCELINPUT_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONCODEINPUT_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONPRESSKEY_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONRELEASEKEY_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONRESTOREKEYBOARDSTATE_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONSAVEKEYBOARDSTATE_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONUPDATESHIFTSTATE_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_SETALPHABETKEYBOARD_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_SETSHIFTED_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_SETSHIFTLOCKED_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_SETSYMBOLSKEYBOARD_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_SETSYMBOLSSHIFTEDKEYBOARD_ENABLED + = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED + = DEFAULT_ENABLED; + private static final boolean LATINIME_ONDISPLAYCOMPLETIONS_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_ONUPDATESELECTION_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED + = DEFAULT_ENABLED; + private static final boolean POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED + = DEFAULT_ENABLED; + private static final boolean POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED + = DEFAULT_ENABLED; + private static final boolean + POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED + = DEFAULT_ENABLED; + private static final boolean POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED = DEFAULT_ENABLED; + private static final boolean POINTERTRACKER_ONDOWNEVENT_ENABLED = DEFAULT_ENABLED; + private static final boolean POINTERTRACKER_ONMOVEEVENT_ENABLED = DEFAULT_ENABLED; + private static final boolean SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED + = DEFAULT_ENABLED; } - public static void logUnstructured(UnsLogGroup logGroup, String details) { + public static void logUnstructured(String logGroup, final String details) { + // TODO: improve performance by making entire class static and/or implementing natively + getInstance().write(LogGroup.UNSTRUCTURED, logGroup + "\t" + details); } private void write(final LogGroup logGroup, final String log) { @@ -282,13 +336,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang builder.append('\t'); builder.append(upTime); builder.append('\t'); builder.append(logGroup.mLogString); builder.append('\t'); builder.append(log); - if (LatinImeLogger.sDBG) { + builder.append('\n'); + if (DEBUG) { Log.d(TAG, "Write: " + '[' + logGroup.mLogString + ']' + log); } if (mLogFileManager.append(builder.toString())) { // success } else { - if (LatinImeLogger.sDBG) { + if (DEBUG) { Log.w(TAG, "Unable to write to log."); } } @@ -300,7 +355,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mLoggingHandler.post(new Runnable() { @Override public void run() { - if (LatinImeLogger.sDBG) { + if (DEBUG) { Log.d(TAG, "Delete log file."); } mLogFileManager.reset(); @@ -315,4 +370,300 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); } + + public static void alphabetShiftState_setShifted(final boolean newShiftState, + final int oldState, final AlphabetShiftState alphabetShiftState) { + if (UnsLogGroup.ALPHABETSHIFTSTATE_SETSHIFTED_ENABLED) { + final String s = "setShifted(" + newShiftState + "): " + oldState + + " > " + alphabetShiftState; + logUnstructured("AlphabetShiftState_setShifted", s); + } + } + + public static void alphabetShiftState_setShiftLocked(final boolean newShiftLockState, + final int oldState, final AlphabetShiftState alphabetShiftState) { + if (UnsLogGroup.ALPHABETSHIFTSTATE_SETSHIFTLOCKED_ENABLED) { + final String s = "setShiftLocked(" + newShiftLockState + "): " + + oldState + " > " + alphabetShiftState; + logUnstructured("AlphabetShiftState_setShiftLocked", s); + } + } + + public static void alphabetShiftState_setAutomaticShifted(final int oldState, + final AlphabetShiftState alphabetShiftState) { + if (UnsLogGroup.ALPHABETSHIFTSTATE_SETAUTOMATICSHIFTED_ENABLED) { + final String s = "setAutomaticShifted: " + oldState + " > " + alphabetShiftState; + logUnstructured("AlphabetShiftState_setAutomaticShifted", s); + } + } + + public static void autoCorrection_hasAutoCorrectionForBinaryDictionary( + final CharSequence consideredWord, final double autoCorrectionThreshold, + final CharSequence autoCorrectionSuggestion, final int autoCorrectionSuggestionScore, + final double normalizedScore) { + if (UnsLogGroup.AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_ENABLED) { + final String s = "Normalized " + consideredWord + "," + + autoCorrectionSuggestion + "," + autoCorrectionSuggestionScore + + ", " + normalizedScore + "(" + autoCorrectionThreshold + ")"; + logUnstructured("AutoCorrection_hasAutoCorrectionForBinaryDictionary", s); + } + } + + public static void autoCorrection_hasAutoCorrectionForBinaryDictionary_bySthreshold() { + if (UnsLogGroup.AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_BYSTHRESHOLD_ENABLED) { + final String s = "Auto corrected by S-threshold."; + logUnstructured("AutoCorrection_hasAutoCorrectionForBinaryDictionar_bySthreshold", s); + } + } + + public static void keyboardState_onCancelInput(final boolean isSinglePointer, + final KeyboardState keyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONCANCELINPUT_ENABLED) { + final String s = "onCancelInput: single=" + isSinglePointer + " " + keyboardState; + logUnstructured("KeyboardState_onCancelInput", s); + } + } + + public static void keyboardState_onCodeInput( + final int code, final boolean isSinglePointer, final boolean autoCaps, + final KeyboardState keyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONCODEINPUT_ENABLED) { + final String s = "onCodeInput: code=" + Keyboard.printableCode(code) + + " single=" + isSinglePointer + + " autoCaps=" + autoCaps + " " + keyboardState; + logUnstructured("KeyboardState_onCodeInput", s); + } + } + + public static void keyboardState_onLongPressTimeout(final int code, + final KeyboardState keyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED) { + final String s = "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + + keyboardState; + logUnstructured("KeyboardState_onLongPressTimeout", s); + } + } + + public static void keyboardState_onPressKey(final int code, + final KeyboardState keyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONPRESSKEY_ENABLED) { + final String s = "onPressKey: code=" + Keyboard.printableCode(code) + " " + + keyboardState; + logUnstructured("KeyboardState_onPressKey", s); + } + } + + public static void keyboardState_onReleaseKey(final KeyboardState keyboardState, final int code, + final boolean withSliding) { + if (UnsLogGroup.KEYBOARDSTATE_ONRELEASEKEY_ENABLED) { + final String s = "onReleaseKey: code=" + Keyboard.printableCode(code) + + " sliding=" + withSliding + " " + keyboardState; + logUnstructured("KeyboardState_onReleaseKey", s); + } + } + + public static void keyboardState_onRestoreKeyboardState(final KeyboardState keyboardState, + final String savedKeyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONRESTOREKEYBOARDSTATE_ENABLED) { + final String s = "onRestoreKeyboardState: saved=" + savedKeyboardState + " " + + keyboardState; + logUnstructured("KeyboardState_onRestoreKeyboardState", s); + } + } + + public static void keyboardState_onSaveKeyboardState(final KeyboardState keyboardState, + final String savedKeyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONSAVEKEYBOARDSTATE_ENABLED) { + final String s = "onSaveKeyboardState: saved=" + savedKeyboardState + " " + + keyboardState; + logUnstructured("KeyboardState_onSaveKeyboardState", s); + } + } + + public static void keyboardState_onUpdateShiftState(final KeyboardState keyboardState, + final boolean autoCaps) { + if (UnsLogGroup.KEYBOARDSTATE_ONUPDATESHIFTSTATE_ENABLED) { + final String s = "onUpdateShiftState: autoCaps=" + autoCaps + " " + keyboardState; + logUnstructured("KeyboardState_onUpdateShiftState", s); + } + } + + public static void keyboardState_setAlphabetKeyboard() { + if (UnsLogGroup.KEYBOARDSTATE_SETALPHABETKEYBOARD_ENABLED) { + final String s = "setAlphabetKeyboard"; + logUnstructured("KeyboardState_setAlphabetKeyboard", s); + } + } + + public static void keyboardState_setShifted(final KeyboardState keyboardState, + final String shiftMode) { + if (UnsLogGroup.KEYBOARDSTATE_SETSHIFTED_ENABLED) { + final String s = "setShifted: shiftMode=" + shiftMode + " " + keyboardState; + logUnstructured("KeyboardState_setShifted", s); + } + } + + public static void keyboardState_setShiftLocked(final KeyboardState keyboardState, + final boolean shiftLocked) { + if (UnsLogGroup.KEYBOARDSTATE_SETSHIFTLOCKED_ENABLED) { + final String s = "setShiftLocked: shiftLocked=" + shiftLocked + " " + keyboardState; + logUnstructured("KeyboardState_setShiftLocked", s); + } + } + + public static void keyboardState_setSymbolsKeyboard() { + if (UnsLogGroup.KEYBOARDSTATE_SETSYMBOLSKEYBOARD_ENABLED) { + final String s = "setSymbolsKeyboard"; + logUnstructured("KeyboardState_setSymbolsKeyboard", s); + } + } + + public static void keyboardState_setSymbolsShiftedKeyboard() { + if (UnsLogGroup.KEYBOARDSTATE_SETSYMBOLSSHIFTEDKEYBOARD_ENABLED) { + final String s = "setSymbolsShiftedKeyboard"; + logUnstructured("KeyboardState_setSymbolsShiftedKeyboard", s); + } + } + + public static void keyboardState_toggleAlphabetAndSymbols(final KeyboardState keyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED) { + final String s = "toggleAlphabetAndSymbols: " + keyboardState; + logUnstructured("KeyboardState_toggleAlphabetAndSymbols", s); + } + } + + public static void latinIME_onDisplayCompletions( + final CompletionInfo[] applicationSpecifiedCompletions) { + if (UnsLogGroup.LATINIME_ONDISPLAYCOMPLETIONS_ENABLED) { + final StringBuilder builder = new StringBuilder(); + builder.append("Received completions:"); + if (applicationSpecifiedCompletions != null) { + for (int i = 0; i < applicationSpecifiedCompletions.length; i++) { + builder.append(" #"); + builder.append(i); + builder.append(": "); + builder.append(applicationSpecifiedCompletions[i]); + builder.append("\n"); + } + } + logUnstructured("LatinIME_onDisplayCompletions", builder.toString()); + } + } + + public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo) { + if (UnsLogGroup.LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED) { + final StringBuilder builder = new StringBuilder(); + builder.append("onStartInputView: editorInfo:"); + builder.append("inputType="); + builder.append(editorInfo.inputType); + builder.append("imeOptions="); + builder.append(editorInfo.imeOptions); + logUnstructured("LatinIME_onStartInputViewInternal", builder.toString()); + } + } + + public static void latinIME_onUpdateSelection(final int lastSelectionStart, + final int lastSelectionEnd, final int oldSelStart, final int oldSelEnd, + final int newSelStart, final int newSelEnd, final int composingSpanStart, + final int composingSpanEnd) { + if (UnsLogGroup.LATINIME_ONUPDATESELECTION_ENABLED) { + final String s = "onUpdateSelection: oss=" + oldSelStart + + ", ose=" + oldSelEnd + + ", lss=" + lastSelectionStart + + ", lse=" + lastSelectionEnd + + ", nss=" + newSelStart + + ", nse=" + newSelEnd + + ", cs=" + composingSpanStart + + ", ce=" + composingSpanEnd; + logUnstructured("LatinIME_onUpdateSelection", s); + } + } + + public static void latinIME_switchToKeyboardView() { + if (UnsLogGroup.LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED) { + final String s = "Switch to keyboard view."; + logUnstructured("LatinIME_switchToKeyboardView", s); + } + } + + public static void latinKeyboardView_onLongPress() { + if (UnsLogGroup.LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED) { + final String s = "long press detected"; + logUnstructured("LatinKeyboardView_onLongPress", s); + } + } + + public static void latinKeyboardView_processMotionEvent(MotionEvent me, int action, + long eventTime, int index, int id, int x, int y) { + if (UnsLogGroup.LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED) { + final float size = me.getSize(index); + final float pressure = me.getPressure(index); + if (action != MotionEvent.ACTION_MOVE) { + getInstance().logMotionEvent(action, eventTime, id, x, y, size, pressure); + } + } + } + + public static void pointerTracker_callListenerOnCancelInput() { + final String s = "onCancelInput"; + if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED) { + logUnstructured("PointerTracker_callListenerOnCancelInput", s); + } + } + + public static void pointerTracker_callListenerOnCodeInput(final Key key, final int x, + final int y, final boolean ignoreModifierKey, final boolean altersCode, + final int code) { + if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED) { + final String s = "onCodeInput: " + Keyboard.printableCode(code) + + " text=" + key.mOutputText + " x=" + x + " y=" + y + + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode + + " enabled=" + key.isEnabled(); + logUnstructured("PointerTracker_callListenerOnCodeInput", s); + } + } + + public static void pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange( + final Key key, final boolean ignoreModifierKey) { + if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED) { + final String s = "onPress : " + KeyDetector.printableCode(key) + + " ignoreModifier=" + ignoreModifierKey + + " enabled=" + key.isEnabled(); + logUnstructured("PointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange", s); + } + } + + public static void pointerTracker_callListenerOnRelease(final Key key, final int primaryCode, + final boolean withSliding, final boolean ignoreModifierKey) { + if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED) { + final String s = "onRelease : " + Keyboard.printableCode(primaryCode) + + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey + + " enabled="+ key.isEnabled(); + logUnstructured("PointerTracker_callListenerOnRelease", s); + } + } + + public static void pointerTracker_onDownEvent(long deltaT, int distanceSquared) { + if (UnsLogGroup.POINTERTRACKER_ONDOWNEVENT_ENABLED) { + final String s = "onDownEvent: ignore potential noise: time=" + deltaT + + " distance=" + distanceSquared; + logUnstructured("PointerTracker_onDownEvent", s); + } + } + + public static void pointerTracker_onMoveEvent(final int x, final int y, final int lastX, + final int lastY) { + if (UnsLogGroup.POINTERTRACKER_ONMOVEEVENT_ENABLED) { + final String s = String.format("onMoveEvent: sudden move is translated to " + + "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y); + logUnstructured("PointerTracker_onMoveEvent", s); + } + } + + public static void suddenJumpingTouchEventHandler_onTouchEvent(final MotionEvent me) { + if (UnsLogGroup.SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED) { + final String s = "onTouchEvent: ignore sudden jump " + me; + logUnstructured("SuddenJumpingTouchEventHandler_onTouchEvent", s); + } + } } -- cgit v1.2.3-83-g751a From a9ca7867b5a7c0be115966211a05f5d460c8638c Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Mon, 9 Apr 2012 10:53:17 -0700 Subject: move suggested words logpoint to SuggestionsView.java Bug: 6188932 Change-Id: I73974783783bb4453962cb9009656d86d2074409 --- .../android/inputmethod/latin/AutoCorrection.java | 11 -------- .../android/inputmethod/latin/ResearchLogger.java | 31 +++++----------------- .../latin/suggestions/SuggestionsView.java | 5 ++++ 3 files changed, 12 insertions(+), 35 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java index 520177afe..38444a10c 100644 --- a/java/src/com/android/inputmethod/latin/AutoCorrection.java +++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java @@ -21,8 +21,6 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import android.text.TextUtils; import android.util.Log; -import com.android.inputmethod.latin.define.ProductionFlag; - import java.util.ArrayList; import java.util.HashMap; @@ -117,19 +115,10 @@ public class AutoCorrection { + autoCorrectionSuggestionScore + ", " + normalizedScore + "(" + autoCorrectionThreshold + ")"); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.autoCorrection_hasAutoCorrectionForBinaryDictionary(consideredWord, - autoCorrectionThreshold, autoCorrectionSuggestion.toString(), - autoCorrectionSuggestionScore, normalizedScore); - } if (normalizedScore >= autoCorrectionThreshold) { if (DBG) { Log.d(TAG, "Auto corrected by S-threshold."); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger - .autoCorrection_hasAutoCorrectionForBinaryDictionary_bySthreshold(); - } return true; } } diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 182a7bc3e..08c26a5df 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -277,11 +277,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final boolean ALPHABETSHIFTSTATE_SETSHIFTLOCKED_ENABLED = DEFAULT_ENABLED; private static final boolean ALPHABETSHIFTSTATE_SETAUTOMATICSHIFTED_ENABLED = DEFAULT_ENABLED; - private static final boolean AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_ENABLED - = DEFAULT_ENABLED; - private static final boolean - AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_BYSTHRESHOLD_ENABLED - = DEFAULT_ENABLED; private static final boolean KEYBOARDSTATE_ONCANCELINPUT_ENABLED = DEFAULT_ENABLED; private static final boolean KEYBOARDSTATE_ONCODEINPUT_ENABLED = DEFAULT_ENABLED; private static final boolean KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED = DEFAULT_ENABLED; @@ -317,6 +312,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final boolean POINTERTRACKER_ONMOVEEVENT_ENABLED = DEFAULT_ENABLED; private static final boolean SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED = DEFAULT_ENABLED; + private static final boolean SUGGESTIONSVIEW_SETSUGGESTIONS_ENABLED = DEFAULT_ENABLED; } public static void logUnstructured(String logGroup, final String details) { @@ -397,25 +393,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - public static void autoCorrection_hasAutoCorrectionForBinaryDictionary( - final CharSequence consideredWord, final double autoCorrectionThreshold, - final CharSequence autoCorrectionSuggestion, final int autoCorrectionSuggestionScore, - final double normalizedScore) { - if (UnsLogGroup.AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_ENABLED) { - final String s = "Normalized " + consideredWord + "," - + autoCorrectionSuggestion + "," + autoCorrectionSuggestionScore - + ", " + normalizedScore + "(" + autoCorrectionThreshold + ")"; - logUnstructured("AutoCorrection_hasAutoCorrectionForBinaryDictionary", s); - } - } - - public static void autoCorrection_hasAutoCorrectionForBinaryDictionary_bySthreshold() { - if (UnsLogGroup.AUTOCORRECTION_HASAUTOCORRECTIONFORBINARYDICTIONARY_BYSTHRESHOLD_ENABLED) { - final String s = "Auto corrected by S-threshold."; - logUnstructured("AutoCorrection_hasAutoCorrectionForBinaryDictionar_bySthreshold", s); - } - } - public static void keyboardState_onCancelInput(final boolean isSinglePointer, final KeyboardState keyboardState) { if (UnsLogGroup.KEYBOARDSTATE_ONCANCELINPUT_ENABLED) { @@ -666,4 +643,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang logUnstructured("SuddenJumpingTouchEventHandler_onTouchEvent", s); } } + + public static void suggestionsView_setSuggestions(SuggestedWords mSuggestedWords) { + if (UnsLogGroup.SUGGESTIONSVIEW_SETSUGGESTIONS_ENABLED) { + logUnstructured("SuggestionsView_setSuggestions", mSuggestedWords.toString()); + } + } } diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java index 1ad37b933..01d51d463 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java @@ -59,10 +59,12 @@ import com.android.inputmethod.keyboard.PointerTracker; import com.android.inputmethod.keyboard.ViewLayoutUtils; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.ResearchLogger; import com.android.inputmethod.latin.StaticInnerHandlerWrapper; import com.android.inputmethod.latin.Suggest; import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.define.ProductionFlag; import java.util.ArrayList; @@ -663,6 +665,9 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, clear(); mSuggestedWords = suggestedWords; mParams.layout(mSuggestedWords, mSuggestionsStrip, this, getWidth()); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.suggestionsView_setSuggestions(mSuggestedWords); + } } public int setMoreSuggestionsHeight(int remainingHeight) { -- cgit v1.2.3-83-g751a From b8e2ae3bc312269897057fccc34cd736c05bcc90 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Mon, 9 Apr 2012 18:39:35 -0700 Subject: change ResearchLoggerTests to check file multi-project commit with I587003f2 Bug: 6188932 Change-Id: I3d3f0c9d011301489473dc330338ea4a7ba61e9e --- java/proguard.flags | 6 + .../android/inputmethod/latin/ResearchLogger.java | 131 +++++++++++++++------ .../android/inputmethod/latin/InputTestsBase.java | 18 +++ 3 files changed, 122 insertions(+), 33 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/proguard.flags b/java/proguard.flags index 44f8581cc..6cc3342dc 100644 --- a/java/proguard.flags +++ b/java/proguard.flags @@ -38,6 +38,12 @@ -keep class com.android.inputmethod.latin.ResearchLogger { void setLogFileManager(...); + void clearAll(); + com.android.inputmethod.latin.ResearchLogger$LogFileManager getLogFileManager(); +} + +-keep class com.android.inputmethod.latin.ResearchLogger$LogFileManager { + java.lang.String getContents(); } -keep class com.android.inputmethod.keyboard.KeyboardLayoutSet$Builder { diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 08c26a5df..2d9f3ceb6 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -35,10 +35,16 @@ import com.android.inputmethod.keyboard.internal.AlphabetShiftState; import com.android.inputmethod.keyboard.internal.KeyboardState; import com.android.inputmethod.latin.define.ProductionFlag; +import java.io.BufferedWriter; import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; import java.io.PrintWriter; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.channels.FileChannel; +import java.nio.charset.Charset; /** * Logs the use of the LatinIME keyboard. @@ -70,15 +76,15 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang * Handles creation, deletion, and provides Readers, Writers, and InputStreams to access * the logs. */ - public static class LogFileManager { - private static final String DEFAULT_FILENAME = "log.txt"; - private static final String DEFAULT_LOG_DIRECTORY = "researchLogger"; + /* package */ static class LogFileManager { + public static final String RESEARCH_LOG_FILENAME_KEY = "RESEARCH_LOG_FILENAME"; + private static final String DEFAULT_FILENAME = "researchLog.txt"; private static final long LOGFILE_PURGE_INTERVAL = 1000 * 60 * 60 * 24; - private InputMethodService mIms; - private File mFile; - private PrintWriter mPrintWriter; + protected InputMethodService mIms; + protected File mFile; + protected PrintWriter mPrintWriter; /* package */ LogFileManager() { } @@ -89,15 +95,28 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang public synchronized boolean createLogFile() { try { - return createLogFile(DEFAULT_LOG_DIRECTORY, DEFAULT_FILENAME); - } catch (final FileNotFoundException e) { + return createLogFile(DEFAULT_FILENAME); + } catch (IOException e) { + e.printStackTrace(); Log.w(TAG, e); return false; } } - public synchronized boolean createLogFile(final String dir, final String filename) - throws FileNotFoundException { + public synchronized boolean createLogFile(final SharedPreferences prefs) { + try { + final String filename = + prefs.getString(RESEARCH_LOG_FILENAME_KEY, DEFAULT_FILENAME); + return createLogFile(filename); + } catch (IOException e) { + Log.w(TAG, e); + e.printStackTrace(); + } + return false; + } + + public synchronized boolean createLogFile(final String filename) + throws IOException { if (mIms == null) { Log.w(TAG, "InputMethodService is not configured. Logging is off."); return false; @@ -107,29 +126,22 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang Log.w(TAG, "Storage directory does not exist. Logging is off."); return false; } - final File directory = new File(filesDir, dir); - if (!directory.exists()) { - final boolean wasCreated = directory.mkdirs(); - if (!wasCreated) { - Log.w(TAG, "Log directory cannot be created. Logging is off."); - return false; - } - } - close(); - mFile = new File(directory, filename); - mFile.setReadable(false, false); + final File file = new File(filesDir, filename); + mFile = file; + file.setReadable(false, false); boolean append = true; - if (mFile.exists() && mFile.lastModified() + LOGFILE_PURGE_INTERVAL < + if (file.exists() && file.lastModified() + LOGFILE_PURGE_INTERVAL < System.currentTimeMillis()) { append = false; } - mPrintWriter = new PrintWriter(new FileOutputStream(mFile, append), true); + mPrintWriter = new PrintWriter(new BufferedWriter(new FileWriter(file, append)), true); return true; } public synchronized boolean append(final String s) { - if (mPrintWriter == null) { + final PrintWriter printWriter = mPrintWriter; + if (printWriter == null) { if (DEBUG) { Log.w(TAG, "PrintWriter is null... attempting to create default log file"); } @@ -140,8 +152,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } } - mPrintWriter.print(s); - return !mPrintWriter.checkError(); + printWriter.print(s); + printWriter.flush(); + return !printWriter.checkError(); } public synchronized void reset() { @@ -149,7 +162,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mPrintWriter.close(); mPrintWriter = null; } - if (mFile != null && mFile.exists()) { + if (mFile != null) { mFile.delete(); mFile = null; } @@ -162,6 +175,53 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mFile = null; } } + + /* package */ synchronized void flush() { + if (mPrintWriter != null) { + mPrintWriter.flush(); + } + } + + /* package */ synchronized String getContents() { + final File file = mFile; + if (file == null) { + return ""; + } + if (mPrintWriter != null) { + mPrintWriter.flush(); + } + FileInputStream stream = null; + FileChannel fileChannel = null; + String s = ""; + try { + stream = new FileInputStream(file); + fileChannel = stream.getChannel(); + final ByteBuffer byteBuffer = ByteBuffer.allocate((int) file.length()); + fileChannel.read(byteBuffer); + byteBuffer.rewind(); + CharBuffer charBuffer = Charset.defaultCharset().decode(byteBuffer); + s = charBuffer.toString(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (fileChannel != null) { + fileChannel.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (stream != null) { + stream.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return s; + } } private ResearchLogger(final LogFileManager logFileManager) { @@ -182,9 +242,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang public void initInternal(final InputMethodService ims, final SharedPreferences prefs) { mIms = ims; - if (mLogFileManager != null) { - mLogFileManager.init(ims); - mLogFileManager.createLogFile(); + final LogFileManager logFileManager = mLogFileManager; + if (logFileManager != null) { + logFileManager.init(ims); + logFileManager.createLogFile(prefs); } if (prefs != null) { sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); @@ -359,6 +420,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang }); } + /* package */ LogFileManager getLogFileManager() { + return mLogFileManager; + } + @Override public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { if (key == null || prefs == null) { @@ -644,7 +709,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - public static void suggestionsView_setSuggestions(SuggestedWords mSuggestedWords) { + public static void suggestionsView_setSuggestions(final SuggestedWords mSuggestedWords) { if (UnsLogGroup.SUGGESTIONSVIEW_SETSUGGESTIONS_ENABLED) { logUnstructured("SuggestionsView_setSuggestions", mSuggestedWords.toString()); } diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java index 4dfe22800..9276b40df 100644 --- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java +++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java @@ -100,6 +100,17 @@ public class InputTestsBase extends ServiceTestCase { return previousDebugSetting; } + // overload this to configure preferences in a way specific to a subclass's tests + protected void configurePreferences() { + // please avoid changing preferences any more than is necessary, as an interruption + // during a test will leave the user's preferences in a bad state. + } + + // restore any preferences set in configurePreferences() + protected void restorePreferences() { + // undo any effects from configurePreferences() + } + @Override protected void setUp() { try { @@ -113,6 +124,7 @@ public class InputTestsBase extends ServiceTestCase { setupService(); mLatinIME = getService(); final boolean previousDebugSetting = setDebugMode(true); + configurePreferences(); mLatinIME.onCreate(); setDebugMode(previousDebugSetting); initSubtypeMap(); @@ -134,6 +146,12 @@ public class InputTestsBase extends ServiceTestCase { changeLanguage("en_US"); } + @Override + protected void tearDown() throws Exception { + super.tearDown(); + restorePreferences(); + } + private void initSubtypeMap() { final InputMethodManager imm = (InputMethodManager)mLatinIME.getSystemService( Context.INPUT_METHOD_SERVICE); -- cgit v1.2.3-83-g751a From 60adb8757496fecb8f376a80832c176b35e43d06 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Thu, 12 Apr 2012 17:13:52 -0700 Subject: clean up researchLogging of autocorrection remove dependence of ResearchLogger on LatinImeLogger for autocorrection multi-project commit with I32cc134b Bug: 6188932 Change-Id: Iaeda97eb43fa4782db2d1b2a6d8d09a93b395111 --- java/src/com/android/inputmethod/latin/LatinIME.java | 4 ++++ java/src/com/android/inputmethod/latin/ResearchLogger.java | 14 +++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 7cdeef897..b587568c9 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1783,6 +1783,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen + "is empty? Impossible! I must commit suicide."); } Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCodePoint); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.LatinIME_commitCurrentAutoCorrection(typedWord, + autoCorrection.toString()); + } mExpectingUpdateSelection = true; commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD, separatorCodePoint); diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 2d9f3ceb6..4e90dd624 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -354,6 +354,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang = DEFAULT_ENABLED; private static final boolean KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_COMMITCURRENTAUTOCORRECTION_ENABLED = DEFAULT_ENABLED; private static final boolean LATINIME_ONDISPLAYCOMPLETIONS_ENABLED = DEFAULT_ENABLED; private static final boolean LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED = DEFAULT_ENABLED; private static final boolean LATINIME_ONUPDATESELECTION_ENABLED = DEFAULT_ENABLED; @@ -574,6 +575,17 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } + public static void LatinIME_commitCurrentAutoCorrection(final String typedWord, + final String autoCorrection) { + if (UnsLogGroup.LATINIME_COMMITCURRENTAUTOCORRECTION_ENABLED) { + if (typedWord.equals(autoCorrection)) { + getInstance().logCorrection("[----]", typedWord, autoCorrection, -1); + } else { + getInstance().logCorrection("[Auto]", typedWord, autoCorrection, -1); + } + } + } + public static void latinIME_onDisplayCompletions( final CompletionInfo[] applicationSpecifiedCompletions) { if (UnsLogGroup.LATINIME_ONDISPLAYCOMPLETIONS_ENABLED) { @@ -714,4 +726,4 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang logUnstructured("SuggestionsView_setSuggestions", mSuggestedWords.toString()); } } -} +} \ No newline at end of file -- cgit v1.2.3-83-g751a From 9bfb6202154e06d7156f2f374dd9359f1be4eb68 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Wed, 11 Apr 2012 21:42:22 -0700 Subject: add logPoint for manual correction (inc touch pos) Bug: 6188932 Change-Id: Ibcc4901bcfab6632ee4c59cb58d35452218a288d --- .../com/android/inputmethod/latin/LatinIME.java | 16 +++++++++++-- .../android/inputmethod/latin/ResearchLogger.java | 28 ++++++++++++++++++++++ .../latin/suggestions/SuggestionsView.java | 8 ++++--- .../android/inputmethod/latin/InputLogicTests.java | 20 ++++++++-------- .../latin/InputLogicTestsNonEnglish.java | 6 ++--- .../android/inputmethod/latin/InputTestsBase.java | 5 ++++ .../inputmethod/latin/PunctuationTests.java | 24 +++++++++---------- 7 files changed, 77 insertions(+), 30 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index caa7f9312..b30d1e35c 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1817,7 +1817,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } @Override - public void pickSuggestionManually(final int index, final CharSequence suggestion) { + public void pickSuggestionManually(final int index, final CharSequence suggestion, + int x, int y) { final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); if (SPACE_STATE_PHANTOM == mSpaceState && suggestion.length() > 0) { @@ -1840,6 +1841,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (ic != null) { final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index]; ic.commitCompletion(completionInfo); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_pickApplicationSpecifiedCompletion(index, + completionInfo.getText(), x, y); + } } return; } @@ -1850,6 +1855,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // So, LatinImeLogger logs "" as a user's input. LatinImeLogger.logOnManualSuggestion("", suggestion.toString(), index, suggestedWords); // Rely on onCodeInput to do the complicated swapping/stripping logic consistently. + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_punctuationSuggestion(index, suggestion, x, y); + } final int primaryCode = suggestion.charAt(0); onCodeInput(primaryCode, KeyboardActionListener.SUGGESTION_STRIP_COORDINATE, @@ -1858,8 +1866,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } // We need to log before we commit, because the word composer will store away the user // typed word. - LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(), + final String replacedWord = mWordComposer.getTypedWord().toString(); + LatinImeLogger.logOnManualSuggestion(replacedWord, suggestion.toString(), index, suggestedWords); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_pickSuggestionManually(replacedWord, index, suggestion, x, y); + } mExpectingUpdateSelection = true; commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK, LastComposedWord.NOT_A_SEPARATOR); diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 4e90dd624..27f2e2a59 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -375,6 +375,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final boolean SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED = DEFAULT_ENABLED; private static final boolean SUGGESTIONSVIEW_SETSUGGESTIONS_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION_ENABLED + = DEFAULT_ENABLED; + private static final boolean LATINIME_PICKPUNCTUATIONSUGGESTION_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_PICKSUGGESTIONMANUALLY_ENABLED = DEFAULT_ENABLED; } public static void logUnstructured(String logGroup, final String details) { @@ -633,6 +637,30 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } + public static void latinIME_pickApplicationSpecifiedCompletion(final int index, + final CharSequence text, int x, int y) { + if (UnsLogGroup.LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION_ENABLED) { + final String s = String.valueOf(index) + '\t' + text + '\t' + x + '\t' + y; + logUnstructured("latinIME_pickApplicationSpecifiedCompletion", s); + } + } + + public static void latinIME_pickSuggestionManually(final String replacedWord, + final int index, CharSequence suggestion, int x, int y) { + if (UnsLogGroup.LATINIME_PICKSUGGESTIONMANUALLY_ENABLED) { + final String s = String.valueOf(index) + '\t' + suggestion + '\t' + x + '\t' + y; + logUnstructured("latinIME_pickSuggestionManually", s); + } + } + + public static void latinIME_punctuationSuggestion(final int index, + final CharSequence suggestion, int x, int y) { + if (UnsLogGroup.LATINIME_PICKPUNCTUATIONSUGGESTION_ENABLED) { + final String s = String.valueOf(index) + '\t' + suggestion + '\t' + x + '\t' + y; + logUnstructured("latinIME_pickPunctuationSuggestion", s); + } + } + public static void latinIME_switchToKeyboardView() { if (UnsLogGroup.LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED) { final String s = "Switch to keyboard view."; diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java index 01d51d463..4e1410415 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java @@ -72,7 +72,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, OnLongClickListener { public interface Listener { public boolean addWordToDictionary(String word); - public void pickSuggestionManually(int index, CharSequence word); + public void pickSuggestionManually(int index, CharSequence word, int x, int y); } // The maximum number of suggestions available. See {@link Suggest#mPrefMaxSuggestions}. @@ -717,7 +717,9 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, public boolean onCustomRequest(int requestCode) { final int index = requestCode; final CharSequence word = mSuggestedWords.getWord(index); - mListener.pickSuggestionManually(index, word); + // TODO: change caller path so coordinates are passed through here + mListener.pickSuggestionManually(index, word, NOT_A_TOUCH_COORDINATE, + NOT_A_TOUCH_COORDINATE); dismissMoreSuggestions(); return true; } @@ -867,7 +869,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, return; final CharSequence word = mSuggestedWords.getWord(index); - mListener.pickSuggestionManually(index, word); + mListener.pickSuggestionManually(index, word, mLastX, mLastY); } @Override diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java index 11eb6ab19..6c3cb16c7 100644 --- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java +++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java @@ -30,7 +30,7 @@ public class InputLogicTests extends InputTestsBase { final String WORD_TO_TYPE = "this"; final String EXPECTED_RESULT = "this"; type(WORD_TO_TYPE); - mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE); + pickSuggestionManually(0, WORD_TO_TYPE); mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); type(Keyboard.CODE_DELETE); assertEquals("press suggestion then backspace", EXPECTED_RESULT, @@ -44,7 +44,7 @@ public class InputLogicTests extends InputTestsBase { type(WORD_TO_TYPE); // Choose the auto-correction, which is always in position 0. For "tgis", the // auto-correction should be "this". - mLatinIME.pickSuggestionManually(0, WORD_TO_PICK); + pickSuggestionManually(0, WORD_TO_PICK); mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); assertEquals("pick typed word over auto-correction then backspace", WORD_TO_PICK, mTextView.getText().toString()); @@ -59,7 +59,7 @@ public class InputLogicTests extends InputTestsBase { type(WORD_TO_TYPE); // Choose the typed word, which should be in position 1 (because position 0 should // be occupied by the "this" auto-correction, as checked by testAutoCorrect()) - mLatinIME.pickSuggestionManually(1, WORD_TO_TYPE); + pickSuggestionManually(1, WORD_TO_TYPE); mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); assertEquals("pick typed word over auto-correction then backspace", WORD_TO_TYPE, mTextView.getText().toString()); @@ -75,7 +75,7 @@ public class InputLogicTests extends InputTestsBase { type(WORD_TO_TYPE); // Choose the second suggestion, which should be in position 2 and should be "thus" // when "tgis is typed. - mLatinIME.pickSuggestionManually(2, WORD_TO_PICK); + pickSuggestionManually(2, WORD_TO_PICK); mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); assertEquals("pick different suggestion then backspace", WORD_TO_PICK, mTextView.getText().toString()); @@ -171,7 +171,7 @@ public class InputLogicTests extends InputTestsBase { final String WORD_TO_TYPE = "this"; final String EXPECTED_RESULT = WORD_TO_TYPE; type(WORD_TO_TYPE); - mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE); + pickSuggestionManually(0, WORD_TO_TYPE); assertEquals("no space after manual pick", EXPECTED_RESULT, mTextView.getText().toString()); } @@ -181,7 +181,7 @@ public class InputLogicTests extends InputTestsBase { final String WORD2_TO_TYPE = "is"; final String EXPECTED_RESULT = "this is"; type(WORD1_TO_TYPE); - mLatinIME.pickSuggestionManually(0, WORD1_TO_TYPE); + pickSuggestionManually(0, WORD1_TO_TYPE); type(WORD2_TO_TYPE); assertEquals("manual pick then type", EXPECTED_RESULT, mTextView.getText().toString()); } @@ -191,7 +191,7 @@ public class InputLogicTests extends InputTestsBase { final String WORD2_TO_TYPE = "!"; final String EXPECTED_RESULT = "this!"; type(WORD1_TO_TYPE); - mLatinIME.pickSuggestionManually(0, WORD1_TO_TYPE); + pickSuggestionManually(0, WORD1_TO_TYPE); type(WORD2_TO_TYPE); assertEquals("manual pick then separator", EXPECTED_RESULT, mTextView.getText().toString()); } @@ -201,7 +201,7 @@ public class InputLogicTests extends InputTestsBase { final String WORD2_TO_TYPE = " is"; final String EXPECTED_RESULT = "this is"; type(WORD1_TO_TYPE); - mLatinIME.pickSuggestionManually(0, WORD1_TO_TYPE); + pickSuggestionManually(0, WORD1_TO_TYPE); type(WORD2_TO_TYPE); assertEquals("manual pick then space then type", EXPECTED_RESULT, mTextView.getText().toString()); @@ -212,11 +212,11 @@ public class InputLogicTests extends InputTestsBase { final String WORD2_TO_PICK = "is"; final String EXPECTED_RESULT = "this is"; type(WORD1_TO_TYPE); - mLatinIME.pickSuggestionManually(0, WORD1_TO_TYPE); + pickSuggestionManually(0, WORD1_TO_TYPE); // Here we fake picking a word through bigram prediction. This test is taking // advantage of the fact that Latin IME blindly trusts the caller of #pickSuggestionManually // to actually pass the right string. - mLatinIME.pickSuggestionManually(1, WORD2_TO_PICK); + pickSuggestionManually(1, WORD2_TO_PICK); assertEquals("manual pick then manual pick", EXPECTED_RESULT, mTextView.getText().toString()); } diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java index b2b9601b6..78143ac5b 100644 --- a/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java +++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java @@ -33,7 +33,7 @@ public class InputLogicTestsNonEnglish extends InputTestsBase { final String EXPECTED_RESULT = "test !"; changeLanguage("fr"); type(WORD1_TO_TYPE); - mLatinIME.pickSuggestionManually(0, WORD1_TO_TYPE); + pickSuggestionManually(0, WORD1_TO_TYPE); type(WORD2_TO_TYPE); assertEquals("manual pick then separator for French", EXPECTED_RESULT, mTextView.getText().toString()); @@ -49,8 +49,8 @@ public class InputLogicTestsNonEnglish extends InputTestsBase { runMessages(); assertTrue("type word then type space should display punctuation strip", mLatinIME.isShowingPunctuationList()); - mLatinIME.pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); - mLatinIME.pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); + pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); + pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); assertEquals("type word then type space then punctuation from strip twice for French", EXPECTED_RESULT, mTextView.getText().toString()); } diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java index 991635e3f..838effe2c 100644 --- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java +++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java @@ -278,6 +278,11 @@ public class InputTestsBase extends ServiceTestCase { waitForDictionaryToBeLoaded(); } + protected void pickSuggestionManually(final int index, final CharSequence suggestion) { + mLatinIME.pickSuggestionManually(index, suggestion, + KeyboardActionListener.NOT_A_TOUCH_COORDINATE, + KeyboardActionListener.NOT_A_TOUCH_COORDINATE); + } // Helper to avoid writing the try{}catch block each time protected static void sleep(final int milliseconds) { diff --git a/tests/src/com/android/inputmethod/latin/PunctuationTests.java b/tests/src/com/android/inputmethod/latin/PunctuationTests.java index b907970f0..e1d4c46f8 100644 --- a/tests/src/com/android/inputmethod/latin/PunctuationTests.java +++ b/tests/src/com/android/inputmethod/latin/PunctuationTests.java @@ -38,8 +38,8 @@ public class PunctuationTests extends InputTestsBase { runMessages(); assertTrue("type word then type space should display punctuation strip", mLatinIME.isShowingPunctuationList()); - mLatinIME.pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); - mLatinIME.pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); + pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); + pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); assertEquals("type word then type space then punctuation from strip twice", EXPECTED_RESULT, mTextView.getText().toString()); } finally { @@ -62,9 +62,9 @@ public class PunctuationTests extends InputTestsBase { final String PUNCTUATION_FROM_STRIP = "!"; final String EXPECTED_RESULT = "this!! is"; type(WORD1_TO_TYPE); - mLatinIME.pickSuggestionManually(0, WORD1_TO_TYPE); - mLatinIME.pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); - mLatinIME.pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); + pickSuggestionManually(0, WORD1_TO_TYPE); + pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); + pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); type(WORD2_TO_TYPE); assertEquals("pick word then pick punctuation twice then type", EXPECTED_RESULT, mTextView.getText().toString()); @@ -75,8 +75,8 @@ public class PunctuationTests extends InputTestsBase { final String WORD2_TO_PICK = "!is"; final String EXPECTED_RESULT = "this!is"; type(WORD1_TO_TYPE); - mLatinIME.pickSuggestionManually(0, WORD1_TO_TYPE); - mLatinIME.pickSuggestionManually(1, WORD2_TO_PICK); + pickSuggestionManually(0, WORD1_TO_TYPE); + pickSuggestionManually(1, WORD2_TO_PICK); assertEquals("manual pick then manual pick a word with punct at start", EXPECTED_RESULT, mTextView.getText().toString()); } @@ -86,7 +86,7 @@ public class PunctuationTests extends InputTestsBase { final String PUNCTUATION = ":"; final String EXPECTED_RESULT = "this:"; type(WORD_TO_TYPE); - mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE); + pickSuggestionManually(0, WORD_TO_TYPE); type(PUNCTUATION); assertEquals("manually pick word then colon", EXPECTED_RESULT, mTextView.getText().toString()); @@ -97,7 +97,7 @@ public class PunctuationTests extends InputTestsBase { final String PUNCTUATION = "("; final String EXPECTED_RESULT = "this ("; type(WORD_TO_TYPE); - mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE); + pickSuggestionManually(0, WORD_TO_TYPE); type(PUNCTUATION); assertEquals("manually pick word then open paren", EXPECTED_RESULT, mTextView.getText().toString()); @@ -108,7 +108,7 @@ public class PunctuationTests extends InputTestsBase { final String PUNCTUATION = ")"; final String EXPECTED_RESULT = "this)"; type(WORD_TO_TYPE); - mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE); + pickSuggestionManually(0, WORD_TO_TYPE); type(PUNCTUATION); assertEquals("manually pick word then close paren", EXPECTED_RESULT, mTextView.getText().toString()); @@ -119,7 +119,7 @@ public class PunctuationTests extends InputTestsBase { final String SPECIAL_KEY = ":-)"; final String EXPECTED_RESULT = "this :-)"; type(WORD_TO_TYPE); - mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE); + pickSuggestionManually(0, WORD_TO_TYPE); mLatinIME.onTextInput(SPECIAL_KEY); assertEquals("manually pick word then press the smiley key", EXPECTED_RESULT, mTextView.getText().toString()); @@ -130,7 +130,7 @@ public class PunctuationTests extends InputTestsBase { final String SPECIAL_KEY = ".com"; final String EXPECTED_RESULT = "this.com"; type(WORD_TO_TYPE); - mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE); + pickSuggestionManually(0, WORD_TO_TYPE); mLatinIME.onTextInput(SPECIAL_KEY); assertEquals("manually pick word then press the .com key", EXPECTED_RESULT, mTextView.getText().toString()); -- cgit v1.2.3-83-g751a From d442984e96cc6299c905141e3e32e0a4f55394c8 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Tue, 17 Apr 2012 18:34:02 -0700 Subject: researchLogging for inputConnection events Bug: 6188932 Change-Id: I596df68956abd879293cfb550e66e7d7d0ba74e9 --- .../com/android/inputmethod/latin/LatinIME.java | 79 +++++++++++++++++++-- .../android/inputmethod/latin/ResearchLogger.java | 81 +++++++++++++++++++--- 2 files changed, 147 insertions(+), 13 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 3c10c4ebf..7d0818193 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1035,6 +1035,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen separatorCode); if (ic != null) { ic.commitText(typedWord, 1); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_commitText(typedWord); + } } addToUserHistoryDictionary(typedWord); } @@ -1059,7 +1062,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (lastTwo != null && lastTwo.length() == 2 && lastTwo.charAt(0) == Keyboard.CODE_SPACE) { ic.deleteSurroundingText(2, 0); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_deleteSurroundingText(2); + } ic.commitText(lastTwo.charAt(1) + " ", 1); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_swapSwapperAndSpaceWhileInBatchEdit(); + } mKeyboardSwitcher.updateShiftState(); } } @@ -1076,6 +1085,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mHandler.cancelDoubleSpacesTimer(); ic.deleteSurroundingText(2, 0); ic.commitText(". ", 1); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_doubleSpaceAutoPeriod(); + } mKeyboardSwitcher.updateShiftState(); return true; } @@ -1089,6 +1101,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (lastOne != null && lastOne.length() == 1 && lastOne.charAt(0) == Keyboard.CODE_SPACE) { ic.deleteSurroundingText(1, 0); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_deleteSurroundingText(1); + } } } @@ -1143,6 +1158,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final InputConnection ic = getCurrentInputConnection(); if (ic != null) { ic.performEditorAction(actionId); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_performEditorAction(actionId); + } } } @@ -1177,6 +1195,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (ic != null) { final String text = new String(new int[] { code }, 0, 1); ic.commitText(text, text.length()); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_sendKeyCodePoint(code); + } } } @@ -1276,6 +1297,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen sendKeyCodePoint(Keyboard.CODE_SPACE); } ic.commitText(text, 1); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_commitText(text); + } ic.endBatchEdit(); mKeyboardSwitcher.updateShiftState(); mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT); @@ -1327,7 +1351,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Cancel multi-character input: remove the text we just entered. // This is triggered on backspace after a key that inputs multiple characters, // like the smiley key or the .com key. - ic.deleteSurroundingText(mEnteredText.length(), 0); + final int length = mEnteredText.length(); + ic.deleteSurroundingText(length, 0); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_deleteSurroundingText(length); + } // If we have mEnteredText, then we know that mHasUncommittedTypedChars == false. // In addition we know that spaceState is false, and that we should not be // reverting any autocorrect at this point. So we can safely return. @@ -1350,6 +1378,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } else { ic.deleteSurroundingText(1, 0); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_deleteSurroundingText(1); + } } } else { if (mLastComposedWord.canRevertCommit()) { @@ -1377,6 +1408,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final int lengthToDelete = mLastSelectionEnd - mLastSelectionStart; ic.setSelection(mLastSelectionEnd, mLastSelectionEnd); ic.deleteSurroundingText(lengthToDelete, 0); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_deleteSurroundingText(lengthToDelete); + } } else { // There is no selection, just delete one character. if (NOT_A_CURSOR_POSITION == mLastSelectionEnd) { @@ -1384,8 +1418,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen Log.e(TAG, "Backspace when we don't know the selection position"); } ic.deleteSurroundingText(1, 0); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_deleteSurroundingText(1); + } if (mDeleteCount > DELETE_ACCELERATE_AT) { ic.deleteSurroundingText(1, 0); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_deleteSurroundingText(1); + } } } if (isSuggestionsRequested()) { @@ -1753,7 +1793,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCodePoint); if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.LatinIME_commitCurrentAutoCorrection(typedWord, + ResearchLogger.latinIME_commitCurrentAutoCorrection(typedWord, autoCorrection.toString()); } mExpectingUpdateSelection = true; @@ -1882,8 +1922,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan( this, bestWord, suggestedWords, mSubtypeSwitcher.isDictionaryAvailable()), 1); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_commitText(bestWord); + } } else { ic.commitText(bestWord, 1); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_commitText(bestWord); + } } } // TODO: figure out here if this is an auto-correct or if the best word is actually @@ -2032,7 +2078,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private void restartSuggestionsOnWordBeforeCursor(final InputConnection ic, final CharSequence word) { mWordComposer.setComposingWord(word, mKeyboardSwitcher.getKeyboard()); - ic.deleteSurroundingText(word.length(), 0); + final int length = word.length(); + ic.deleteSurroundingText(length, 0); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_deleteSurroundingText(length); + } ic.setComposingText(word, 1); mHandler.postUpdateSuggestions(); } @@ -2045,12 +2095,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final int separatorLength = LastComposedWord.getSeparatorLength( mLastComposedWord.mSeparatorCode); // TODO: should we check our saved separator against the actual contents of the text view? + final int deleteLength = cancelLength + separatorLength; if (DEBUG) { if (mWordComposer.isComposingWord()) { throw new RuntimeException("revertCommit, but we are composing a word"); } final String wordBeforeCursor = - ic.getTextBeforeCursor(cancelLength + separatorLength, 0) + ic.getTextBeforeCursor(deleteLength, 0) .subSequence(0, cancelLength).toString(); if (!TextUtils.equals(committedWord, wordBeforeCursor)) { throw new RuntimeException("revertCommit check failed: we thought we were " @@ -2058,7 +2109,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen + "\", but before the cursor we found \"" + wordBeforeCursor + "\""); } } - ic.deleteSurroundingText(cancelLength + separatorLength, 0); + ic.deleteSurroundingText(deleteLength, 0); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_deleteSurroundingText(deleteLength); + } if (0 == separatorLength || mLastComposedWord.didCommitTypedWord()) { // This is the case when we cancel a manual pick. // We should restart suggestion on the word right away. @@ -2070,6 +2124,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen sendKeyCodePoint(mLastComposedWord.mSeparatorCode); Utils.Stats.onSeparator(mLastComposedWord.mSeparatorCode, WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_revertCommit(originallyTypedWord); + } // Don't restart suggestion yet. We'll restart if the user deletes the // separator. } @@ -2093,7 +2150,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen return false; } ic.deleteSurroundingText(2, 0); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_deleteSurroundingText(2); + } ic.commitText(" ", 1); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_revertDoubleSpaceWhileInBatchEdit(); + } return true; } @@ -2114,7 +2177,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } ic.beginBatchEdit(); ic.deleteSurroundingText(2, 0); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_deleteSurroundingText(2); + } ic.commitText(" " + textBeforeCursor.subSequence(0, 1), 1); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_revertSwapPunctuation(); + } ic.endBatchEdit(); return true; } diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 27f2e2a59..7072dda23 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -355,9 +355,24 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final boolean KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED = DEFAULT_ENABLED; private static final boolean LATINIME_COMMITCURRENTAUTOCORRECTION_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_COMMITTEXT_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_DELETESURROUNDINGTEXT_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_DOUBLESPACEAUTOPERIOD_ENABLED = DEFAULT_ENABLED; private static final boolean LATINIME_ONDISPLAYCOMPLETIONS_ENABLED = DEFAULT_ENABLED; private static final boolean LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED = DEFAULT_ENABLED; private static final boolean LATINIME_ONUPDATESELECTION_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_PERFORMEDITORACTION_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION_ENABLED + = DEFAULT_ENABLED; + private static final boolean LATINIME_PICKPUNCTUATIONSUGGESTION_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_PICKSUGGESTIONMANUALLY_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_REVERTCOMMIT_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT_ENABLED + = DEFAULT_ENABLED; + private static final boolean LATINIME_REVERTSWAPPUNCTUATION_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_SENDKEYCODEPOINT_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT_ENABLED + = DEFAULT_ENABLED; private static final boolean LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED = DEFAULT_ENABLED; private static final boolean LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED = DEFAULT_ENABLED; private static final boolean LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED @@ -375,10 +390,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final boolean SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED = DEFAULT_ENABLED; private static final boolean SUGGESTIONSVIEW_SETSUGGESTIONS_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION_ENABLED - = DEFAULT_ENABLED; - private static final boolean LATINIME_PICKPUNCTUATIONSUGGESTION_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_PICKSUGGESTIONMANUALLY_ENABLED = DEFAULT_ENABLED; } public static void logUnstructured(String logGroup, final String details) { @@ -579,7 +590,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - public static void LatinIME_commitCurrentAutoCorrection(final String typedWord, + public static void latinIME_commitCurrentAutoCorrection(final String typedWord, final String autoCorrection) { if (UnsLogGroup.LATINIME_COMMITCURRENTAUTOCORRECTION_ENABLED) { if (typedWord.equals(autoCorrection)) { @@ -590,6 +601,24 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } + public static void latinIME_commitText(final CharSequence typedWord) { + if (UnsLogGroup.LATINIME_COMMITTEXT_ENABLED) { + logUnstructured("LatinIME_commitText", typedWord.toString()); + } + } + + public static void latinIME_deleteSurroundingText(final int length) { + if (UnsLogGroup.LATINIME_DELETESURROUNDINGTEXT_ENABLED) { + logUnstructured("LatinIME_deleteSurroundingText", String.valueOf(length)); + } + } + + public static void latinIME_doubleSpaceAutoPeriod() { + if (UnsLogGroup.LATINIME_DOUBLESPACEAUTOPERIOD_ENABLED) { + logUnstructured("LatinIME_doubleSpaceAutoPeriod", ""); + } + } + public static void latinIME_onDisplayCompletions( final CompletionInfo[] applicationSpecifiedCompletions) { if (UnsLogGroup.LATINIME_ONDISPLAYCOMPLETIONS_ENABLED) { @@ -637,11 +666,17 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } + public static void latinIME_performEditorAction(final int imeActionNext) { + if (UnsLogGroup.LATINIME_PERFORMEDITORACTION_ENABLED) { + logUnstructured("LatinIME_performEditorAction", String.valueOf(imeActionNext)); + } + } + public static void latinIME_pickApplicationSpecifiedCompletion(final int index, final CharSequence text, int x, int y) { if (UnsLogGroup.LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION_ENABLED) { final String s = String.valueOf(index) + '\t' + text + '\t' + x + '\t' + y; - logUnstructured("latinIME_pickApplicationSpecifiedCompletion", s); + logUnstructured("LatinIME_pickApplicationSpecifiedCompletion", s); } } @@ -649,7 +684,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final int index, CharSequence suggestion, int x, int y) { if (UnsLogGroup.LATINIME_PICKSUGGESTIONMANUALLY_ENABLED) { final String s = String.valueOf(index) + '\t' + suggestion + '\t' + x + '\t' + y; - logUnstructured("latinIME_pickSuggestionManually", s); + logUnstructured("LatinIME_pickSuggestionManually", s); } } @@ -657,7 +692,31 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final CharSequence suggestion, int x, int y) { if (UnsLogGroup.LATINIME_PICKPUNCTUATIONSUGGESTION_ENABLED) { final String s = String.valueOf(index) + '\t' + suggestion + '\t' + x + '\t' + y; - logUnstructured("latinIME_pickPunctuationSuggestion", s); + logUnstructured("LatinIME_pickPunctuationSuggestion", s); + } + } + + public static void latinIME_revertDoubleSpaceWhileInBatchEdit() { + if (UnsLogGroup.LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT_ENABLED) { + logUnstructured("LatinIME_revertDoubleSpaceWhileInBatchEdit", ""); + } + } + + public static void latinIME_revertSwapPunctuation() { + if (UnsLogGroup.LATINIME_REVERTSWAPPUNCTUATION_ENABLED) { + logUnstructured("LatinIME_revertSwapPunctuation", ""); + } + } + + public static void latinIME_sendKeyCodePoint(final int code) { + if (UnsLogGroup.LATINIME_SENDKEYCODEPOINT_ENABLED) { + logUnstructured("LatinIME_sendKeyCodePoint", String.valueOf(code)); + } + } + + public static void latinIME_swapSwapperAndSpaceWhileInBatchEdit() { + if (UnsLogGroup.LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT_ENABLED) { + logUnstructured("latinIME_swapSwapperAndSpaceWhileInBatchEdit", ""); } } @@ -686,6 +745,12 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } + public static void latinIME_revertCommit(final String originallyTypedWord) { + if (UnsLogGroup.LATINIME_REVERTCOMMIT_ENABLED) { + logUnstructured("LatinIME_revertCommit", originallyTypedWord); + } + } + public static void pointerTracker_callListenerOnCancelInput() { final String s = "onCancelInput"; if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED) { -- cgit v1.2.3-83-g751a From 48a7681e064ae259b840f0e757da2d716043d893 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Tue, 17 Apr 2012 20:54:33 -0700 Subject: researchLogger detail on IME sessions log device type, screen size, etc. also simplification inside ResearchLogger to use exceptions better, and fix ResearchLoggerTests to not change preferences to specify the logfile. multi-project change with Idfd193b16260215cca32886e288f03a0c12b2781 Bug: 6188932 Change-Id: Idd3ca6eb8e8e3934f68234b241c7fd7d0cc3bcd5 --- .../inputmethod/keyboard/LatinKeyboardView.java | 3 + .../com/android/inputmethod/latin/LatinIME.java | 2 +- .../android/inputmethod/latin/ResearchLogger.java | 157 ++++++++++++++------- .../android/inputmethod/latin/InputTestsBase.java | 26 +--- 4 files changed, 109 insertions(+), 79 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index efb0d77ea..d50d096c6 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -467,6 +467,9 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke mSpaceIcon = (mSpaceKey != null) ? mSpaceKey.getIcon(keyboard.mIconsSet) : null; final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap; mSpacebarTextSize = keyHeight * mSpacebarTextRatio; + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinKeyboardView_setKeyboard(keyboard); + } } /** diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 41884d34a..861c23b04 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -634,7 +634,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen editorInfo.inputType, editorInfo.imeOptions)); } if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.latinIME_onStartInputViewInternal(editorInfo); + ResearchLogger.latinIME_onStartInputViewInternal(editorInfo, mPrefs); } if (InputAttributes.inPrivateImeOptions(null, NO_MICROPHONE_COMPAT, editorInfo)) { Log.w(TAG, "Deprecated private IME option specified: " diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 7072dda23..384ed79a8 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -18,10 +18,12 @@ package com.android.inputmethod.latin; import android.content.SharedPreferences; import android.inputmethodservice.InputMethodService; +import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import android.os.Process; import android.os.SystemClock; +import android.preference.PreferenceManager; import android.text.TextUtils; import android.util.Log; import android.view.MotionEvent; @@ -45,6 +47,7 @@ import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; +import java.util.Map; /** * Logs the use of the LatinIME keyboard. @@ -68,7 +71,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang * Isolates management of files. This variable should never be null, but can be changed * to support testing. */ - private LogFileManager mLogFileManager; + /* package */ LogFileManager mLogFileManager; /** * Manages the file(s) that stores the logs. @@ -93,63 +96,53 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mIms = ims; } - public synchronized boolean createLogFile() { - try { - return createLogFile(DEFAULT_FILENAME); - } catch (IOException e) { - e.printStackTrace(); - Log.w(TAG, e); - return false; - } + public synchronized void createLogFile() throws IOException { + createLogFile(DEFAULT_FILENAME); } - public synchronized boolean createLogFile(final SharedPreferences prefs) { - try { - final String filename = - prefs.getString(RESEARCH_LOG_FILENAME_KEY, DEFAULT_FILENAME); - return createLogFile(filename); - } catch (IOException e) { - Log.w(TAG, e); - e.printStackTrace(); - } - return false; + public synchronized void createLogFile(final SharedPreferences prefs) + throws IOException { + final String filename = + prefs.getString(RESEARCH_LOG_FILENAME_KEY, DEFAULT_FILENAME); + createLogFile(filename); } - public synchronized boolean createLogFile(final String filename) + public synchronized void createLogFile(final String filename) throws IOException { if (mIms == null) { - Log.w(TAG, "InputMethodService is not configured. Logging is off."); - return false; + final String msg = "InputMethodService is not configured. Logging is off."; + Log.w(TAG, msg); + throw new IOException(msg); } final File filesDir = mIms.getFilesDir(); if (filesDir == null || !filesDir.exists()) { - Log.w(TAG, "Storage directory does not exist. Logging is off."); - return false; + final String msg = "Storage directory does not exist. Logging is off."; + Log.w(TAG, msg); + throw new IOException(msg); } close(); final File file = new File(filesDir, filename); mFile = file; - file.setReadable(false, false); boolean append = true; if (file.exists() && file.lastModified() + LOGFILE_PURGE_INTERVAL < System.currentTimeMillis()) { append = false; } mPrintWriter = new PrintWriter(new BufferedWriter(new FileWriter(file, append)), true); - return true; } public synchronized boolean append(final String s) { - final PrintWriter printWriter = mPrintWriter; - if (printWriter == null) { + PrintWriter printWriter = mPrintWriter; + if (printWriter == null || !mFile.exists()) { if (DEBUG) { Log.w(TAG, "PrintWriter is null... attempting to create default log file"); } - if (!createLogFile()) { - if (DEBUG) { - Log.w(TAG, "Failed to create log file. Not logging."); - return false; - } + try { + createLogFile(); + printWriter = mPrintWriter; + } catch (IOException e) { + Log.w(TAG, "Failed to create log file. Not logging."); + return false; } } printWriter.print(s); @@ -161,9 +154,15 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang if (mPrintWriter != null) { mPrintWriter.close(); mPrintWriter = null; + if (DEBUG) { + Log.d(TAG, "logfile closed"); + } } if (mFile != null) { mFile.delete(); + if (DEBUG) { + Log.d(TAG, "logfile deleted"); + } mFile = null; } } @@ -173,6 +172,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mPrintWriter.close(); mPrintWriter = null; mFile = null; + if (DEBUG) { + Log.d(TAG, "logfile closed"); + } } } @@ -240,12 +242,16 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang sInstance.initInternal(ims, prefs); } - public void initInternal(final InputMethodService ims, final SharedPreferences prefs) { + /* package */ void initInternal(final InputMethodService ims, final SharedPreferences prefs) { mIms = ims; final LogFileManager logFileManager = mLogFileManager; if (logFileManager != null) { logFileManager.init(ims); - logFileManager.createLogFile(prefs); + try { + logFileManager.createLogFile(prefs); + } catch (IOException e) { + e.printStackTrace(); + } } if (prefs != null) { sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); @@ -253,19 +259,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - /** - * Change to a different logFileManager. - * - * @throws IllegalArgumentException if logFileManager is null - */ - void setLogFileManager(final LogFileManager manager) { - if (manager == null) { - throw new IllegalArgumentException("warning: trying to set null logFileManager"); - } else { - mLogFileManager = manager; - } - } - /** * Represents a category of logging events that share the same subfield structure. */ @@ -377,6 +370,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final boolean LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED = DEFAULT_ENABLED; private static final boolean LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINKEYBOARDVIEW_SETKEYBOARD_ENABLED = DEFAULT_ENABLED; private static final boolean POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED = DEFAULT_ENABLED; private static final boolean POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED @@ -413,12 +407,21 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang if (DEBUG) { Log.d(TAG, "Write: " + '[' + logGroup.mLogString + ']' + log); } - if (mLogFileManager.append(builder.toString())) { + final String s = builder.toString(); + if (mLogFileManager.append(s)) { // success } else { if (DEBUG) { Log.w(TAG, "Unable to write to log."); } + // perhaps logfile was deleted. try to recreate and relog. + try { + mLogFileManager.createLogFile(PreferenceManager + .getDefaultSharedPreferences(mIms)); + mLogFileManager.append(s); + } catch (IOException e) { + e.printStackTrace(); + } } } }); @@ -474,6 +477,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } + // TODO: Remove keyboardState logging that is redundant in light of + // latinKeyboardView_setKeyboard public static void keyboardState_onCancelInput(final boolean isSinglePointer, final KeyboardState keyboardState) { if (UnsLogGroup.KEYBOARDSTATE_ONCANCELINPUT_ENABLED) { @@ -637,14 +642,22 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo) { + public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo, + final SharedPreferences prefs) { if (UnsLogGroup.LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED) { final StringBuilder builder = new StringBuilder(); builder.append("onStartInputView: editorInfo:"); - builder.append("inputType="); - builder.append(editorInfo.inputType); - builder.append("imeOptions="); - builder.append(editorInfo.imeOptions); + builder.append("\tinputType="); + builder.append(Integer.toHexString(editorInfo.inputType)); + builder.append("\timeOptions="); + builder.append(Integer.toHexString(editorInfo.imeOptions)); + builder.append("\tdisplay="); builder.append(Build.DISPLAY); + builder.append("\tmodel="); builder.append(Build.MODEL); + for (Map.Entry entry : prefs.getAll().entrySet()) { + builder.append("\t" + entry.getKey()); + Object value = entry.getValue(); + builder.append("=" + ((value == null) ? "" : value.toString())); + } logUnstructured("LatinIME_onStartInputViewInternal", builder.toString()); } } @@ -745,6 +758,42 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } + public static void latinKeyboardView_setKeyboard(final Keyboard keyboard) { + if (UnsLogGroup.LATINKEYBOARDVIEW_SETKEYBOARD_ENABLED) { + StringBuilder builder = new StringBuilder(); + builder.append("id="); + builder.append(keyboard.mId); + builder.append("\tw="); + builder.append(keyboard.mOccupiedWidth); + builder.append("\th="); + builder.append(keyboard.mOccupiedHeight); + builder.append("\tkeys=["); + boolean first = true; + for (Key key : keyboard.mKeys) { + if (first) { + first = false; + } else { + builder.append(","); + } + builder.append("{code:"); + builder.append(key.mCode); + builder.append(",altCode:"); + builder.append(key.mAltCode); + builder.append(",x:"); + builder.append(key.mX); + builder.append(",y:"); + builder.append(key.mY); + builder.append(",w:"); + builder.append(key.mWidth); + builder.append(",h:"); + builder.append(key.mHeight); + builder.append("}"); + } + builder.append("]"); + logUnstructured("LatinKeyboardView_setKeyboard", builder.toString()); + } + } + public static void latinIME_revertCommit(final String originallyTypedWord) { if (UnsLogGroup.LATINIME_REVERTCOMMIT_ENABLED) { logUnstructured("LatinIME_revertCommit", originallyTypedWord); diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java index 838effe2c..c73a931ea 100644 --- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java +++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java @@ -107,31 +107,15 @@ public class InputTestsBase extends ServiceTestCase { return setBooleanPreference(PREF_DEBUG_MODE, value, false); } - // overload this to configure preferences in a way specific to a subclass's tests - protected void configurePreferences() { - // please avoid changing preferences any more than is necessary, as an interruption - // during a test will leave the user's preferences in a bad state. - } - - // restore any preferences set in configurePreferences() - protected void restorePreferences() { - // undo any effects from configurePreferences() - } - @Override - protected void setUp() { - try { - super.setUp(); - } catch (Exception e) { - e.printStackTrace(); - } + protected void setUp() throws Exception { + super.setUp(); mTextView = new TextView(getContext()); mTextView.setInputType(InputType.TYPE_CLASS_TEXT); mTextView.setEnabled(true); setupService(); mLatinIME = getService(); final boolean previousDebugSetting = setDebugMode(true); - configurePreferences(); mLatinIME.onCreate(); setDebugMode(previousDebugSetting); initSubtypeMap(); @@ -153,12 +137,6 @@ public class InputTestsBase extends ServiceTestCase { changeLanguage("en_US"); } - @Override - protected void tearDown() throws Exception { - super.tearDown(); - restorePreferences(); - } - private void initSubtypeMap() { final InputMethodManager imm = (InputMethodManager)mLatinIME.getSystemService( Context.INPUT_METHOD_SERVICE); -- cgit v1.2.3-83-g751a From c59d74ce476cc9edcb30f739bd8d37feacf218c4 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Thu, 19 Apr 2012 20:31:30 -0700 Subject: remove unnecessary KeyboardState logging Bug: 6188932 Change-Id: Iafbb1825777122a1810fa3339853263aced3077e --- .../keyboard/internal/AlphabetShiftState.java | 12 --- .../keyboard/internal/KeyboardState.java | 27 ----- .../android/inputmethod/latin/ResearchLogger.java | 114 --------------------- 3 files changed, 153 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java index 392afca97..5712df1fc 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java @@ -18,9 +18,6 @@ package com.android.inputmethod.keyboard.internal; import android.util.Log; -import com.android.inputmethod.latin.ResearchLogger; -import com.android.inputmethod.latin.define.ProductionFlag; - public class AlphabetShiftState { private static final String TAG = AlphabetShiftState.class.getSimpleName(); private static final boolean DEBUG = false; @@ -62,9 +59,6 @@ public class AlphabetShiftState { } if (DEBUG) Log.d(TAG, "setShifted(" + newShiftState + "): " + toString(oldState) + " > " + this); - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.alphabetShiftState_setShifted(newShiftState, oldState, this); - } } public void setShiftLocked(boolean newShiftLockState) { @@ -84,9 +78,6 @@ public class AlphabetShiftState { if (DEBUG) Log.d(TAG, "setShiftLocked(" + newShiftLockState + "): " + toString(oldState) + " > " + this); - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.alphabetShiftState_setShiftLocked(newShiftLockState, oldState, this); - } } public void setAutomaticShifted() { @@ -94,9 +85,6 @@ public class AlphabetShiftState { mState = AUTOMATIC_SHIFTED; if (DEBUG) Log.d(TAG, "setAutomaticShifted: " + toString(oldState) + " > " + this); - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.alphabetShiftState_setAutomaticShifted(oldState, this); - } } public boolean isShiftedOrShiftLocked() { diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index 6949c9d12..2d80a798d 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -141,9 +141,6 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onSaveKeyboardState: saved=" + state + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onSaveKeyboardState(this, state.toString()); - } } private void onRestoreKeyboardState() { @@ -151,9 +148,6 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onRestoreKeyboardState: saved=" + state + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onRestoreKeyboardState(this, state.toString()); - } if (!state.mIsValid || state.mIsAlphabetMode) { setAlphabetKeyboard(); } else { @@ -186,9 +180,6 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode) + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_setShifted(this, shiftModeToString(shiftMode)); - } if (!mIsAlphabetMode) return; final int prevShiftMode; if (mAlphabetShiftState.isAutomaticShifted()) { @@ -228,9 +219,6 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setShiftLocked: shiftLocked=" + shiftLocked + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_setShiftLocked(this, shiftLocked); - } if (!mIsAlphabetMode) return; if (shiftLocked && (!mAlphabetShiftState.isShiftLocked() || mAlphabetShiftState.isShiftLockShifted())) { @@ -246,9 +234,6 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "toggleAlphabetAndSymbols: " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_toggleAlphabetAndSymbols(this); - } if (mIsAlphabetMode) { mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked(); if (mPrevSymbolsKeyboardWasShifted) { @@ -280,9 +265,6 @@ public class KeyboardState { Log.d(TAG, "setAlphabetKeyboard"); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_setAlphabetKeyboard(); - } mSwitchActions.setAlphabetKeyboard(); mIsAlphabetMode = true; mIsSymbolShifted = false; @@ -294,9 +276,6 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setSymbolsKeyboard"); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_setSymbolsKeyboard(); - } mSwitchActions.setSymbolsKeyboard(); mIsAlphabetMode = false; mIsSymbolShifted = false; @@ -309,9 +288,6 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setSymbolsShiftedKeyboard"); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_setSymbolsShiftedKeyboard(); - } mSwitchActions.setSymbolsShiftedKeyboard(); mIsAlphabetMode = false; mIsSymbolShifted = true; @@ -399,9 +375,6 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onUpdateShiftState(this, autoCaps); - } updateAlphabetShiftState(autoCaps); } diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 384ed79a8..566af7061 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -33,7 +33,6 @@ import android.view.inputmethod.EditorInfo; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.keyboard.internal.AlphabetShiftState; import com.android.inputmethod.keyboard.internal.KeyboardState; import com.android.inputmethod.latin.define.ProductionFlag; @@ -327,26 +326,11 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang public static class UnsLogGroup { private static final boolean DEFAULT_ENABLED = true; - private static final boolean ALPHABETSHIFTSTATE_SETSHIFTED_ENABLED = DEFAULT_ENABLED; - private static final boolean ALPHABETSHIFTSTATE_SETSHIFTLOCKED_ENABLED = DEFAULT_ENABLED; - private static final boolean ALPHABETSHIFTSTATE_SETAUTOMATICSHIFTED_ENABLED - = DEFAULT_ENABLED; private static final boolean KEYBOARDSTATE_ONCANCELINPUT_ENABLED = DEFAULT_ENABLED; private static final boolean KEYBOARDSTATE_ONCODEINPUT_ENABLED = DEFAULT_ENABLED; private static final boolean KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED = DEFAULT_ENABLED; private static final boolean KEYBOARDSTATE_ONPRESSKEY_ENABLED = DEFAULT_ENABLED; private static final boolean KEYBOARDSTATE_ONRELEASEKEY_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_ONRESTOREKEYBOARDSTATE_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_ONSAVEKEYBOARDSTATE_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_ONUPDATESHIFTSTATE_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_SETALPHABETKEYBOARD_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_SETSHIFTED_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_SETSHIFTLOCKED_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_SETSYMBOLSKEYBOARD_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_SETSYMBOLSSHIFTEDKEYBOARD_ENABLED - = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED - = DEFAULT_ENABLED; private static final boolean LATINIME_COMMITCURRENTAUTOCORRECTION_ENABLED = DEFAULT_ENABLED; private static final boolean LATINIME_COMMITTEXT_ENABLED = DEFAULT_ENABLED; private static final boolean LATINIME_DELETESURROUNDINGTEXT_ENABLED = DEFAULT_ENABLED; @@ -451,34 +435,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); } - public static void alphabetShiftState_setShifted(final boolean newShiftState, - final int oldState, final AlphabetShiftState alphabetShiftState) { - if (UnsLogGroup.ALPHABETSHIFTSTATE_SETSHIFTED_ENABLED) { - final String s = "setShifted(" + newShiftState + "): " + oldState - + " > " + alphabetShiftState; - logUnstructured("AlphabetShiftState_setShifted", s); - } - } - - public static void alphabetShiftState_setShiftLocked(final boolean newShiftLockState, - final int oldState, final AlphabetShiftState alphabetShiftState) { - if (UnsLogGroup.ALPHABETSHIFTSTATE_SETSHIFTLOCKED_ENABLED) { - final String s = "setShiftLocked(" + newShiftLockState + "): " - + oldState + " > " + alphabetShiftState; - logUnstructured("AlphabetShiftState_setShiftLocked", s); - } - } - - public static void alphabetShiftState_setAutomaticShifted(final int oldState, - final AlphabetShiftState alphabetShiftState) { - if (UnsLogGroup.ALPHABETSHIFTSTATE_SETAUTOMATICSHIFTED_ENABLED) { - final String s = "setAutomaticShifted: " + oldState + " > " + alphabetShiftState; - logUnstructured("AlphabetShiftState_setAutomaticShifted", s); - } - } - - // TODO: Remove keyboardState logging that is redundant in light of - // latinKeyboardView_setKeyboard public static void keyboardState_onCancelInput(final boolean isSinglePointer, final KeyboardState keyboardState) { if (UnsLogGroup.KEYBOARDSTATE_ONCANCELINPUT_ENABLED) { @@ -525,76 +481,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - public static void keyboardState_onRestoreKeyboardState(final KeyboardState keyboardState, - final String savedKeyboardState) { - if (UnsLogGroup.KEYBOARDSTATE_ONRESTOREKEYBOARDSTATE_ENABLED) { - final String s = "onRestoreKeyboardState: saved=" + savedKeyboardState + " " - + keyboardState; - logUnstructured("KeyboardState_onRestoreKeyboardState", s); - } - } - - public static void keyboardState_onSaveKeyboardState(final KeyboardState keyboardState, - final String savedKeyboardState) { - if (UnsLogGroup.KEYBOARDSTATE_ONSAVEKEYBOARDSTATE_ENABLED) { - final String s = "onSaveKeyboardState: saved=" + savedKeyboardState + " " - + keyboardState; - logUnstructured("KeyboardState_onSaveKeyboardState", s); - } - } - - public static void keyboardState_onUpdateShiftState(final KeyboardState keyboardState, - final boolean autoCaps) { - if (UnsLogGroup.KEYBOARDSTATE_ONUPDATESHIFTSTATE_ENABLED) { - final String s = "onUpdateShiftState: autoCaps=" + autoCaps + " " + keyboardState; - logUnstructured("KeyboardState_onUpdateShiftState", s); - } - } - - public static void keyboardState_setAlphabetKeyboard() { - if (UnsLogGroup.KEYBOARDSTATE_SETALPHABETKEYBOARD_ENABLED) { - final String s = "setAlphabetKeyboard"; - logUnstructured("KeyboardState_setAlphabetKeyboard", s); - } - } - - public static void keyboardState_setShifted(final KeyboardState keyboardState, - final String shiftMode) { - if (UnsLogGroup.KEYBOARDSTATE_SETSHIFTED_ENABLED) { - final String s = "setShifted: shiftMode=" + shiftMode + " " + keyboardState; - logUnstructured("KeyboardState_setShifted", s); - } - } - - public static void keyboardState_setShiftLocked(final KeyboardState keyboardState, - final boolean shiftLocked) { - if (UnsLogGroup.KEYBOARDSTATE_SETSHIFTLOCKED_ENABLED) { - final String s = "setShiftLocked: shiftLocked=" + shiftLocked + " " + keyboardState; - logUnstructured("KeyboardState_setShiftLocked", s); - } - } - - public static void keyboardState_setSymbolsKeyboard() { - if (UnsLogGroup.KEYBOARDSTATE_SETSYMBOLSKEYBOARD_ENABLED) { - final String s = "setSymbolsKeyboard"; - logUnstructured("KeyboardState_setSymbolsKeyboard", s); - } - } - - public static void keyboardState_setSymbolsShiftedKeyboard() { - if (UnsLogGroup.KEYBOARDSTATE_SETSYMBOLSSHIFTEDKEYBOARD_ENABLED) { - final String s = "setSymbolsShiftedKeyboard"; - logUnstructured("KeyboardState_setSymbolsShiftedKeyboard", s); - } - } - - public static void keyboardState_toggleAlphabetAndSymbols(final KeyboardState keyboardState) { - if (UnsLogGroup.KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED) { - final String s = "toggleAlphabetAndSymbols: " + keyboardState; - logUnstructured("KeyboardState_toggleAlphabetAndSymbols", s); - } - } - public static void latinIME_commitCurrentAutoCorrection(final String typedWord, final String autoCorrection) { if (UnsLogGroup.LATINIME_COMMITCURRENTAUTOCORRECTION_ENABLED) { -- cgit v1.2.3-83-g751a From 623118fe48aedee4028eca5eb4791273fc10e9a5 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Mon, 30 Apr 2012 11:03:50 -0700 Subject: log packageName in researchLogger on startup Bug: 6188932 Change-Id: I85f434bf284d6b481893f7d41c884a4f0c57ce49 --- java/src/com/android/inputmethod/latin/ResearchLogger.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 566af7061..b9f796483 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -533,6 +533,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang if (UnsLogGroup.LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED) { final StringBuilder builder = new StringBuilder(); builder.append("onStartInputView: editorInfo:"); + builder.append("\tpackageName="); + builder.append(editorInfo.packageName); builder.append("\tinputType="); builder.append(Integer.toHexString(editorInfo.inputType)); builder.append("\timeOptions="); -- cgit v1.2.3-83-g751a From 77814c4bb0670c3a20c5e636890d70ea1a144409 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Wed, 2 May 2012 14:33:48 -0700 Subject: associate a per-device UUID with the researchLog logged upon starting a session Bug: 6188932 Change-Id: I197d231fbc1d87cf5a3649b485a9be4b17898ba3 --- .../com/android/inputmethod/latin/ResearchLogger.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index b9f796483..7e7b2b1ea 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -17,6 +17,7 @@ package com.android.inputmethod.latin; import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; import android.inputmethodservice.InputMethodService; import android.os.Build; import android.os.Handler; @@ -47,6 +48,7 @@ import java.nio.CharBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.util.Map; +import java.util.UUID; /** * Logs the use of the LatinIME keyboard. @@ -59,6 +61,7 @@ import java.util.Map; public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = ResearchLogger.class.getSimpleName(); private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; + private static final String PREF_RESEARCH_LOGGER_UUID_STRING = "pref_research_logger_uuid"; private static final boolean DEBUG = false; private static final ResearchLogger sInstance = new ResearchLogger(new LogFileManager()); @@ -546,10 +549,23 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang Object value = entry.getValue(); builder.append("=" + ((value == null) ? "" : value.toString())); } + builder.append("\tuuid="); builder.append(getUUID(prefs)); logUnstructured("LatinIME_onStartInputViewInternal", builder.toString()); } } + private static String getUUID(final SharedPreferences prefs) { + String uuidString = prefs.getString(PREF_RESEARCH_LOGGER_UUID_STRING, null); + if (null == uuidString) { + UUID uuid = UUID.randomUUID(); + uuidString = uuid.toString(); + Editor editor = prefs.edit(); + editor.putString(PREF_RESEARCH_LOGGER_UUID_STRING, uuidString); + editor.apply(); + } + return uuidString; + } + 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, -- cgit v1.2.3-83-g751a From d67a248de45a698d1009757c9f4e750c77bf35f1 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Tue, 1 May 2012 22:09:53 -0700 Subject: record full text after finishing session uses onWindowHidden() callback as proxy for finishing session. Bug: 6188932 Change-Id: Ic63b47c946ca91fc35f80d71b2f9e24e2d0339ac --- .../com/android/inputmethod/latin/LatinIME.java | 13 +++++- .../android/inputmethod/latin/ResearchLogger.java | 51 +++++++++++++++++++++- 2 files changed, 60 insertions(+), 4 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 7efdef987..624c322a0 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -702,6 +702,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen @Override public void onWindowHidden() { + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_onWindowHidden(mLastSelectionStart, mLastSelectionEnd, + getCurrentInputConnection()); + } super.onWindowHidden(); KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); if (inputView != null) inputView.closing(); @@ -732,7 +736,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen int composingSpanStart, int composingSpanEnd) { super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, composingSpanEnd); - if (DEBUG) { Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart + ", ose=" + oldSelEnd @@ -744,9 +747,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen + ", ce=" + composingSpanEnd); } if (ProductionFlag.IS_EXPERIMENTAL) { + final boolean expectingUpdateSelectionFromLogger = + ResearchLogger.getAndClearLatinIMEExpectingUpdateSelection(); ResearchLogger.latinIME_onUpdateSelection(mLastSelectionStart, mLastSelectionEnd, oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, - composingSpanEnd); + composingSpanEnd, mExpectingUpdateSelection, + expectingUpdateSelectionFromLogger); + if (expectingUpdateSelectionFromLogger) { + return; + } } // TODO: refactor the following code to be less contrived. diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 566af7061..92fb0c408 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -29,6 +29,7 @@ import android.util.Log; import android.view.MotionEvent; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputConnection; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.KeyDetector; @@ -62,10 +63,15 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final boolean DEBUG = false; private static final ResearchLogger sInstance = new ResearchLogger(new LogFileManager()); + private static final int MAX_INPUTVIEW_LENGTH_TO_CAPTURE = 8192; // must be >=1 public static boolean sIsLogging = false; /* package */ final Handler mLoggingHandler; private InputMethodService mIms; + // set when LatinIME should ignore a onUpdateSelection() callback that + // arises from operations in this class + private static boolean mLatinIMEExpectingUpdateSelection = false; + /** * Isolates management of files. This variable should never be null, but can be changed * to support testing. @@ -336,6 +342,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final boolean LATINIME_DELETESURROUNDINGTEXT_ENABLED = DEFAULT_ENABLED; private static final boolean LATINIME_DOUBLESPACEAUTOPERIOD_ENABLED = DEFAULT_ENABLED; private static final boolean LATINIME_ONDISPLAYCOMPLETIONS_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_ONWINDOWHIDDEN_ENABLED = DEFAULT_ENABLED; private static final boolean LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED = DEFAULT_ENABLED; private static final boolean LATINIME_ONUPDATESELECTION_ENABLED = DEFAULT_ENABLED; private static final boolean LATINIME_PERFORMEDITORACTION_ENABLED = DEFAULT_ENABLED; @@ -528,6 +535,43 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } + /* package */ static boolean getAndClearLatinIMEExpectingUpdateSelection() { + boolean returnValue = mLatinIMEExpectingUpdateSelection; + mLatinIMEExpectingUpdateSelection = false; + return returnValue; + } + + public static void latinIME_onWindowHidden(final int savedSelectionStart, + final int savedSelectionEnd, final InputConnection ic) { + if (UnsLogGroup.LATINIME_ONWINDOWHIDDEN_ENABLED) { + if (ic != null) { + ic.beginBatchEdit(); + ic.performContextMenuAction(android.R.id.selectAll); + CharSequence charSequence = ic.getSelectedText(0); + ic.setSelection(savedSelectionStart, savedSelectionEnd); + ic.endBatchEdit(); + mLatinIMEExpectingUpdateSelection = true; + if (TextUtils.isEmpty(charSequence)) { + logUnstructured("LatinIME_onWindowHidden", ""); + } else { + if (charSequence.length() > MAX_INPUTVIEW_LENGTH_TO_CAPTURE) { + // do not cut in the middle of a supplementary character + int length = MAX_INPUTVIEW_LENGTH_TO_CAPTURE; + if (!Character.isLetter(charSequence.charAt(length))) { + length--; + } + final CharSequence truncatedCharSequence = charSequence.subSequence(0, + length); + logUnstructured("LatinIME_onWindowHidden", truncatedCharSequence.toString() + + ""); + } else { + logUnstructured("LatinIME_onWindowHidden", charSequence.toString()); + } + } + } + } + } + public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo, final SharedPreferences prefs) { if (UnsLogGroup.LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED) { @@ -551,7 +595,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang 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 int composingSpanEnd, final boolean expectingUpdateSelection, + final boolean expectingUpdateSelectionFromLogger) { if (UnsLogGroup.LATINIME_ONUPDATESELECTION_ENABLED) { final String s = "onUpdateSelection: oss=" + oldSelStart + ", ose=" + oldSelEnd @@ -560,7 +605,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang + ", nss=" + newSelStart + ", nse=" + newSelEnd + ", cs=" + composingSpanStart - + ", ce=" + composingSpanEnd; + + ", ce=" + composingSpanEnd + + ", eus=" + expectingUpdateSelection + + ", eusfl=" + expectingUpdateSelectionFromLogger; logUnstructured("LatinIME_onUpdateSelection", s); } } -- cgit v1.2.3-83-g751a From aec44d50a7534d8704a7006b4f90f5e8040a931b Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Wed, 9 May 2012 16:04:26 -0700 Subject: include text context in researchLogger when logging LatinIME.onUpdateSelection(), now include the current word and preceding word. no escaping of the word is performed; this is temporary until the output format is cleaned up. also fix EditingUtils.getWordRangeAtCursor to support supplementary UTF-16 characters. Bug: 6188932 Change-Id: If4612a2627537d5d8bb2f9585a3ad1b4e56c2e26 --- .../android/inputmethod/latin/EditingUtils.java | 52 ++++++- .../com/android/inputmethod/latin/LatinIME.java | 2 +- .../android/inputmethod/latin/ResearchLogger.java | 13 +- .../inputmethod/latin/EditingUtilsTests.java | 161 +++++++++++++++++++++ .../com/android/inputmethod/latin/UtilsTests.java | 65 --------- 5 files changed, 215 insertions(+), 78 deletions(-) create mode 100644 tests/src/com/android/inputmethod/latin/EditingUtilsTests.java delete mode 100644 tests/src/com/android/inputmethod/latin/UtilsTests.java (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/EditingUtils.java b/java/src/com/android/inputmethod/latin/EditingUtils.java index 93106ac27..be4cb7787 100644 --- a/java/src/com/android/inputmethod/latin/EditingUtils.java +++ b/java/src/com/android/inputmethod/latin/EditingUtils.java @@ -54,7 +54,7 @@ public class EditingUtils { */ public static String getWordAtCursor(InputConnection connection, String separators) { // getWordRangeAtCursor returns null if the connection is null - Range r = getWordRangeAtCursor(connection, separators); + Range r = getWordRangeAtCursor(connection, separators, 0); return (r == null) ? null : r.mWord; } @@ -84,7 +84,17 @@ public class EditingUtils { } } - private static Range getWordRangeAtCursor(InputConnection connection, String sep) { + /** + * Returns the text surrounding the cursor. + * + * @param connection the InputConnection to the TextView + * @param sep a string of characters that split words. + * @param additionalPrecedingWordsCount the number of words before the current word that should + * be included in the returned range + * @return a range containing the text surrounding the cursor + */ + public static Range getWordRangeAtCursor(InputConnection connection, String sep, + int additionalPrecedingWordsCount) { if (connection == null || sep == null) { return null; } @@ -94,14 +104,40 @@ public class EditingUtils { return null; } - // Find first word separator before the cursor + // Going backward, alternate skipping non-separators and separators until enough words + // have been read. int start = before.length(); - while (start > 0 && !isWhitespace(before.charAt(start - 1), sep)) start--; + boolean isStoppingAtWhitespace = true; // toggles to indicate what to stop at + while (true) { // see comments below for why this is guaranteed to halt + while (start > 0) { + final int codePoint = Character.codePointBefore(before, start); + if (isStoppingAtWhitespace == isSeparator(codePoint, sep)) { + break; // inner loop + } + --start; + if (Character.isSupplementaryCodePoint(codePoint)) { + --start; + } + } + // isStoppingAtWhitespace is true every other time through the loop, + // so additionalPrecedingWordsCount is guaranteed to become < 0, which + // guarantees outer loop termination + if (isStoppingAtWhitespace && (--additionalPrecedingWordsCount < 0)) { + break; // outer loop + } + isStoppingAtWhitespace = !isStoppingAtWhitespace; + } // Find last word separator after the cursor int end = -1; - while (++end < after.length() && !isWhitespace(after.charAt(end), sep)) { - // Nothing to do here. + while (++end < after.length()) { + final int codePoint = Character.codePointAt(after, end); + if (isSeparator(codePoint, sep)) { + break; + } + if (Character.isSupplementaryCodePoint(codePoint)) { + ++end; + } } int cursor = getCursorPosition(connection); @@ -114,8 +150,8 @@ public class EditingUtils { return null; } - private static boolean isWhitespace(int code, String whitespace) { - return whitespace.contains(String.valueOf((char) code)); + private static boolean isSeparator(int code, String sep) { + return sep.indexOf(code) != -1; } private static final Pattern spaceRegex = Pattern.compile("\\s+"); diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index e8211aecf..b7385ed21 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -755,7 +755,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen ResearchLogger.latinIME_onUpdateSelection(mLastSelectionStart, mLastSelectionEnd, oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, composingSpanEnd, mExpectingUpdateSelection, - expectingUpdateSelectionFromLogger); + expectingUpdateSelectionFromLogger, getCurrentInputConnection()); if (expectingUpdateSelectionFromLogger) { return; } diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 92a9633de..a46ed03af 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -36,6 +36,7 @@ import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.internal.KeyboardState; +import com.android.inputmethod.latin.EditingUtils.Range; import com.android.inputmethod.latin.define.ProductionFlag; import java.io.BufferedWriter; @@ -64,6 +65,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; private static final String PREF_RESEARCH_LOGGER_UUID_STRING = "pref_research_logger_uuid"; private static final boolean DEBUG = false; + private static final String WHITESPACE_SEPARATORS = " \t\n\r"; private static final ResearchLogger sInstance = new ResearchLogger(new LogFileManager()); private static final int MAX_INPUTVIEW_LENGTH_TO_CAPTURE = 8192; // must be >=1 @@ -558,9 +560,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang logUnstructured("LatinIME_onWindowHidden", ""); } else { if (charSequence.length() > MAX_INPUTVIEW_LENGTH_TO_CAPTURE) { - // do not cut in the middle of a supplementary character int length = MAX_INPUTVIEW_LENGTH_TO_CAPTURE; - if (!Character.isLetter(charSequence.charAt(length))) { + // 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, @@ -614,7 +617,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang 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 boolean expectingUpdateSelectionFromLogger, final InputConnection connection) { if (UnsLogGroup.LATINIME_ONUPDATESELECTION_ENABLED) { final String s = "onUpdateSelection: oss=" + oldSelStart + ", ose=" + oldSelEnd @@ -625,7 +628,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang + ", cs=" + composingSpanStart + ", ce=" + composingSpanEnd + ", eus=" + expectingUpdateSelection - + ", eusfl=" + expectingUpdateSelectionFromLogger; + + ", eusfl=" + expectingUpdateSelectionFromLogger + + ", context=\"" + EditingUtils.getWordRangeAtCursor(connection, + WHITESPACE_SEPARATORS, 1).mWord + "\""; logUnstructured("LatinIME_onUpdateSelection", s); } } diff --git a/tests/src/com/android/inputmethod/latin/EditingUtilsTests.java b/tests/src/com/android/inputmethod/latin/EditingUtilsTests.java new file mode 100644 index 000000000..c73f8891f --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/EditingUtilsTests.java @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2010 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.latin; + +import android.test.AndroidTestCase; +import android.view.inputmethod.ExtractedText; +import android.view.inputmethod.ExtractedTextRequest; +import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputConnectionWrapper; + +import com.android.inputmethod.latin.EditingUtils.Range; + +public class EditingUtilsTests extends AndroidTestCase { + + // The following is meant to be a reasonable default for + // the "word_separators" resource. + private static final String sSeparators = ".,:;!?-"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + private class MockConnection extends InputConnectionWrapper { + final String mTextBefore; + final String mTextAfter; + final ExtractedText mExtractedText; + + public MockConnection(String textBefore, String textAfter, ExtractedText extractedText) { + super(null, false); + mTextBefore = textBefore; + mTextAfter = textAfter; + mExtractedText = extractedText; + } + + /* (non-Javadoc) + * @see android.view.inputmethod.InputConnectionWrapper#getTextBeforeCursor(int, int) + */ + @Override + public CharSequence getTextBeforeCursor(int n, int flags) { + return mTextBefore; + } + + /* (non-Javadoc) + * @see android.view.inputmethod.InputConnectionWrapper#getTextAfterCursor(int, int) + */ + @Override + public CharSequence getTextAfterCursor(int n, int flags) { + return mTextAfter; + } + + /* (non-Javadoc) + * @see android.view.inputmethod.InputConnectionWrapper#getExtractedText(ExtractedTextRequest, int) + */ + @Override + public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) { + return mExtractedText; + } + } + + /************************** Tests ************************/ + + /** + * Test for getting previous word (for bigram suggestions) + */ + public void testGetPreviousWord() { + // If one of the following cases breaks, the bigram suggestions won't work. + assertEquals(EditingUtils.getPreviousWord("abc def", sSeparators), "abc"); + assertNull(EditingUtils.getPreviousWord("abc", sSeparators)); + assertNull(EditingUtils.getPreviousWord("abc. def", sSeparators)); + + // The following tests reflect the current behavior of the function + // EditingUtils#getPreviousWord. + // TODO: However at this time, the code does never go + // into such a path, so it should be safe to change the behavior of + // this function if needed - especially since it does not seem very + // logical. These tests are just there to catch any unintentional + // changes in the behavior of the EditingUtils#getPreviousWord method. + assertEquals(EditingUtils.getPreviousWord("abc def ", sSeparators), "abc"); + assertEquals(EditingUtils.getPreviousWord("abc def.", sSeparators), "abc"); + assertEquals(EditingUtils.getPreviousWord("abc def .", sSeparators), "def"); + assertNull(EditingUtils.getPreviousWord("abc ", sSeparators)); + } + + /** + * Test for getting the word before the cursor (for bigram) + */ + public void testGetThisWord() { + assertEquals(EditingUtils.getThisWord("abc def", sSeparators), "def"); + assertEquals(EditingUtils.getThisWord("abc def ", sSeparators), "def"); + assertNull(EditingUtils.getThisWord("abc def.", sSeparators)); + assertNull(EditingUtils.getThisWord("abc def .", sSeparators)); + } + + /** + * Test logic in getting the word range at the cursor. + */ + public void testGetWordRangeAtCursor() { + ExtractedText et = new ExtractedText(); + InputConnection mockConnection; + mockConnection = new MockConnection("word wo", "rd", et); + et.startOffset = 0; + et.selectionStart = 7; + Range r; + + // basic case + r = EditingUtils.getWordRangeAtCursor(mockConnection, " ", 0); + assertEquals("word", r.mWord); + r = null; + + // more than one word + r = EditingUtils.getWordRangeAtCursor(mockConnection, " ", 1); + assertEquals("word word", r.mWord); + r = null; + + // tab character instead of space + mockConnection = new MockConnection("one\tword\two", "rd", et); + r = EditingUtils.getWordRangeAtCursor(mockConnection, "\t", 1); + assertEquals("word\tword", r.mWord); + r = null; + + // only one word doesn't go too far + mockConnection = new MockConnection("one\tword\two", "rd", et); + r = EditingUtils.getWordRangeAtCursor(mockConnection, "\t", 1); + assertEquals("word\tword", r.mWord); + r = null; + + // tab or space + mockConnection = new MockConnection("one word\two", "rd", et); + r = EditingUtils.getWordRangeAtCursor(mockConnection, " \t", 1); + assertEquals("word\tword", r.mWord); + r = null; + + // tab or space multiword + mockConnection = new MockConnection("one word\two", "rd", et); + r = EditingUtils.getWordRangeAtCursor(mockConnection, " \t", 2); + assertEquals("one word\tword", r.mWord); + r = null; + + // splitting on supplementary character + final String supplementaryChar = "\uD840\uDC8A"; + mockConnection = new MockConnection("one word" + supplementaryChar + "wo", "rd", et); + r = EditingUtils.getWordRangeAtCursor(mockConnection, supplementaryChar, 0); + assertEquals("word", r.mWord); + r = null; + } +} diff --git a/tests/src/com/android/inputmethod/latin/UtilsTests.java b/tests/src/com/android/inputmethod/latin/UtilsTests.java deleted file mode 100644 index 2ef4e2ff5..000000000 --- a/tests/src/com/android/inputmethod/latin/UtilsTests.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2010,2011 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.latin; - -import android.test.AndroidTestCase; - -public class UtilsTests extends AndroidTestCase { - - // The following is meant to be a reasonable default for - // the "word_separators" resource. - private static final String sSeparators = ".,:;!?-"; - - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - /************************** Tests ************************/ - - /** - * Test for getting previous word (for bigram suggestions) - */ - public void testGetPreviousWord() { - // If one of the following cases breaks, the bigram suggestions won't work. - assertEquals(EditingUtils.getPreviousWord("abc def", sSeparators), "abc"); - assertNull(EditingUtils.getPreviousWord("abc", sSeparators)); - assertNull(EditingUtils.getPreviousWord("abc. def", sSeparators)); - - // The following tests reflect the current behavior of the function - // EditingUtils#getPreviousWord. - // TODO: However at this time, the code does never go - // into such a path, so it should be safe to change the behavior of - // this function if needed - especially since it does not seem very - // logical. These tests are just there to catch any unintentional - // changes in the behavior of the EditingUtils#getPreviousWord method. - assertEquals(EditingUtils.getPreviousWord("abc def ", sSeparators), "abc"); - assertEquals(EditingUtils.getPreviousWord("abc def.", sSeparators), "abc"); - assertEquals(EditingUtils.getPreviousWord("abc def .", sSeparators), "def"); - assertNull(EditingUtils.getPreviousWord("abc ", sSeparators)); - } - - /** - * Test for getting the word before the cursor (for bigram) - */ - public void testGetThisWord() { - assertEquals(EditingUtils.getThisWord("abc def", sSeparators), "def"); - assertEquals(EditingUtils.getThisWord("abc def ", sSeparators), "def"); - assertNull(EditingUtils.getThisWord("abc def.", sSeparators)); - assertNull(EditingUtils.getThisWord("abc def .", sSeparators)); - } -} -- cgit v1.2.3-83-g751a From 553e2f19c1607080ff874cb642237f947809cdb3 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 18 May 2012 16:45:26 +0900 Subject: Change auto caps mode argument to int type Bug: 6501446 Change-Id: I3f7bc0fc39edd29ebf96107c3d43b9ccc9b8022e --- .../keyboard/internal/KeyboardState.java | 15 ++++++----- .../com/android/inputmethod/latin/Constants.java | 15 +++++++++++ .../com/android/inputmethod/latin/LatinIME.java | 19 +++++++------ .../android/inputmethod/latin/ResearchLogger.java | 2 +- .../internal/KeyboardStateMultiTouchTests.java | 4 +-- .../internal/KeyboardStateSingleTouchTests.java | 31 ++++++++++------------ .../keyboard/internal/KeyboardStateTestsBase.java | 4 +-- .../keyboard/internal/MockKeyboardSwitcher.java | 30 ++++++++++++++------- 8 files changed, 73 insertions(+), 47 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index 2d80a798d..e3661a9f8 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -20,6 +20,7 @@ import android.text.TextUtils; import android.util.Log; import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.ResearchLogger; import com.android.inputmethod.latin.define.ProductionFlag; @@ -30,8 +31,8 @@ import com.android.inputmethod.latin.define.ProductionFlag; * * The input events are {@link #onLoadKeyboard(String)}, {@link #onSaveKeyboardState()}, * {@link #onPressKey(int)}, {@link #onReleaseKey(int, boolean)}, - * {@link #onCodeInput(int, boolean, boolean)}, {@link #onCancelInput(boolean)}, - * {@link #onUpdateShiftState(boolean)}, {@link #onLongPressTimeout(int)}. + * {@link #onCodeInput(int, boolean, int)}, {@link #onCancelInput(boolean)}, + * {@link #onUpdateShiftState(int)}, {@link #onLongPressTimeout(int)}. * * The actions are {@link SwitchActions}'s methods. */ @@ -50,7 +51,7 @@ public class KeyboardState { public void setSymbolsShiftedKeyboard(); /** - * Request to call back {@link KeyboardState#onUpdateShiftState(boolean)}. + * Request to call back {@link KeyboardState#onUpdateShiftState(int)}. */ public void requestUpdatingShiftState(); @@ -371,14 +372,14 @@ public class KeyboardState { } } - public void onUpdateShiftState(boolean autoCaps) { + public void onUpdateShiftState(int autoCaps) { if (DEBUG_EVENT) { Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this); } updateAlphabetShiftState(autoCaps); } - private void updateAlphabetShiftState(boolean autoCaps) { + private void updateAlphabetShiftState(int autoCaps) { if (!mIsAlphabetMode) return; if (!mShiftKeyState.isReleasing()) { // Ignore update shift state event while the shift key is being pressed (including @@ -386,7 +387,7 @@ public class KeyboardState { return; } if (!mAlphabetShiftState.isShiftLocked() && !mShiftKeyState.isIgnoring()) { - if (mShiftKeyState.isReleasing() && autoCaps) { + if (mShiftKeyState.isReleasing() && autoCaps != Constants.TextUtils.CAP_MODE_OFF) { // Only when shift key is releasing, automatic temporary upper case will be set. setShifted(AUTOMATIC_SHIFT); } else { @@ -521,7 +522,7 @@ public class KeyboardState { return false; } - public void onCodeInput(int code, boolean isSinglePointer, boolean autoCaps) { + public void onCodeInput(int code, boolean isSinglePointer, int autoCaps) { if (DEBUG_EVENT) { Log.d(TAG, "onCodeInput: code=" + Keyboard.printableCode(code) + " single=" + isSinglePointer diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java index 7c2284569..e79db367c 100644 --- a/java/src/com/android/inputmethod/latin/Constants.java +++ b/java/src/com/android/inputmethod/latin/Constants.java @@ -106,6 +106,21 @@ public final class Constants { } } + public static class TextUtils { + /** + * Capitalization mode for {@link android.text.TextUtils#getCapsMode}: don't capitalize + * characters. This value may be used with + * {@link android.text.TextUtils#CAP_MODE_CHARACTERS}, + * {@link android.text.TextUtils#CAP_MODE_WORDS}, and + * {@link android.text.TextUtils#CAP_MODE_SENTENCES}. + */ + public static final int CAP_MODE_OFF = 0; + + private TextUtils() { + // This utility class is not publicly instantiable. + } + } + private Constants() { // This utility class is not publicly instantiable. } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index bdefaee92..b632d34bf 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1032,26 +1032,28 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen updateSuggestions(); } - public boolean getCurrentAutoCapsState() { - if (!mSettingsValues.mAutoCap) return false; + public int getCurrentAutoCapsState() { + if (!mSettingsValues.mAutoCap) return Constants.TextUtils.CAP_MODE_OFF; final EditorInfo ei = getCurrentInputEditorInfo(); - if (ei == null) return false; + if (ei == null) return Constants.TextUtils.CAP_MODE_OFF; final int inputType = ei.inputType; - if ((inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) return true; + if ((inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) { + return TextUtils.CAP_MODE_CHARACTERS; + } final boolean noNeedToCheckCapsMode = (inputType & (InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_CAP_WORDS)) == 0; - if (noNeedToCheckCapsMode) return false; + if (noNeedToCheckCapsMode) return Constants.TextUtils.CAP_MODE_OFF; final InputConnection ic = getCurrentInputConnection(); - if (ic == null) return false; + if (ic == null) return Constants.TextUtils.CAP_MODE_OFF; // TODO: This blocking IPC call is heavy. Consider doing this without using IPC calls. // Note: getCursorCapsMode() returns the current capitalization mode that is any // combination of CAP_MODE_CHARACTERS, CAP_MODE_WORDS, and CAP_MODE_SENTENCES. 0 means none // of them. - return ic.getCursorCapsMode(inputType) != 0; + return ic.getCursorCapsMode(inputType); } // "ic" may be null @@ -1522,7 +1524,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (ic != null) { // If it's the first letter, make note of auto-caps state if (mWordComposer.size() == 1) { - mWordComposer.setAutoCapitalized(getCurrentAutoCapsState()); + mWordComposer.setAutoCapitalized( + getCurrentAutoCapsState() != Constants.TextUtils.CAP_MODE_OFF); } ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); } diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 566af7061..aa979a66f 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -444,7 +444,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } public static void keyboardState_onCodeInput( - final int code, final boolean isSinglePointer, final boolean autoCaps, + final int code, final boolean isSinglePointer, final int autoCaps, final KeyboardState keyboardState) { if (UnsLogGroup.KEYBOARDSTATE_ONCODEINPUT_ENABLED) { final String s = "onCodeInput: code=" + Keyboard.printableCode(code) diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java index 0e6caaf87..c2408c9c5 100644 --- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java +++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java @@ -206,8 +206,8 @@ public class KeyboardStateMultiTouchTests extends KeyboardStateTestsBase { // Chording input in automatic upper case. public void testChordingAutomaticUpperCase() { - // Set auto caps mode on. - setAutoCapsMode(AUTO_CAPS); + // Set capitalize the first character of all words mode. + setAutoCapsMode(CAP_MODE_WORDS); // Update shift state with auto caps enabled. pressAndReleaseKey(CODE_AUTO_CAPS_TRIGGER, ALPHABET_UNSHIFTED, ALPHABET_AUTOMATIC_SHIFTED); diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java index de2a50fcf..b9f53184a 100644 --- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java +++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java @@ -202,8 +202,8 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase { // Automatic upper case test public void testAutomaticUpperCase() { - // Set auto caps mode on. - setAutoCapsMode(AUTO_CAPS); + // Set capitalize the first character of all words mode. + setAutoCapsMode(CAP_MODE_WORDS); // Load keyboard, should be in automatic shifted. loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED); @@ -239,7 +239,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase { // Long press shift key. public void testLongPressShift() { // Set auto caps mode off. - setAutoCapsMode(NO_AUTO_CAPS); + setAutoCapsMode(CAP_MODE_OFF); // Load keyboard, should be in alphabet. loadKeyboard(ALPHABET_UNSHIFTED); // Long press shift key, enter alphabet shift locked. @@ -268,8 +268,8 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase { // Press/release shift key, back to alphabet. pressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED); - // Set auto caps mode on. - setAutoCapsMode(AUTO_CAPS); + // Set capitalize the first character of all words mode. + setAutoCapsMode(CAP_MODE_WORDS); // Load keyboard, should be in automatic shifted. loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED); // Long press shift key, enter alphabet shift locked. @@ -303,8 +303,8 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase { // Second shift key tap. secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); - // Set auto caps mode on. - setAutoCapsMode(AUTO_CAPS); + // Set capitalize the first character of all words mode. + setAutoCapsMode(CAP_MODE_WORDS); // Load keyboard, should be in automatic shifted. loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED); @@ -322,7 +322,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase { // Update shift state. public void testUpdateShiftState() { // Set auto caps mode off. - setAutoCapsMode(NO_AUTO_CAPS); + setAutoCapsMode(CAP_MODE_OFF); // Load keyboard, should be in alphabet. loadKeyboard(ALPHABET_UNSHIFTED); // Update shift state, remained in alphabet. @@ -350,8 +350,8 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase { // Update shift state, remained in symbols shifted. updateShiftState(SYMBOLS_SHIFTED); - // Set auto caps mode on. - setAutoCapsMode(AUTO_CAPS); + // Set capitalize the first character of all words mode. + setAutoCapsMode(CAP_MODE_WORDS); // Load keyboard, should be in automatic shifted. loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED); // Update shift state, remained in automatic shifted. @@ -592,11 +592,8 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase { // Change focus to auto caps text field. public void testChangeFocusAutoCaps() { - // Set auto caps mode on. - setAutoCapsMode(AUTO_CAPS); - - // Update shift state. - updateShiftState(ALPHABET_AUTOMATIC_SHIFTED); + // Set capitalize the first character of all words mode. + setAutoCapsMode(CAP_MODE_WORDS); // Change focus to new text field. loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED); @@ -735,8 +732,8 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase { // Rapidly press/release letter key. secondPressAndReleaseKey('J', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); - // Set auto caps mode on. - setAutoCapsMode(AUTO_CAPS); + // Set capitalize the first character of all words mode. + setAutoCapsMode(CAP_MODE_WORDS); // Press/release auto caps trigger letter to enter alphabet automatic shifted. pressAndReleaseKey(CODE_AUTO_CAPS_TRIGGER, ALPHABET_UNSHIFTED, ALPHABET_AUTOMATIC_SHIFTED); // Press/release shift key diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java index 96a54668c..bbe0dbde5 100644 --- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java +++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java @@ -29,12 +29,12 @@ public class KeyboardStateTestsBase extends AndroidTestCase super.setUp(); mSwitcher = new MockKeyboardSwitcher(); - mSwitcher.setAutoCapsMode(NO_AUTO_CAPS); + mSwitcher.setAutoCapsMode(CAP_MODE_OFF); loadKeyboard(ALPHABET_UNSHIFTED); } - public void setAutoCapsMode(boolean autoCaps) { + public void setAutoCapsMode(int autoCaps) { mSwitcher.setAutoCapsMode(autoCaps); } diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java index 999e08a8d..485ea61e7 100644 --- a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java +++ b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java @@ -16,6 +16,8 @@ package com.android.inputmethod.keyboard.internal; +import android.text.TextUtils; + import com.android.inputmethod.keyboard.Keyboard; public class MockKeyboardSwitcher implements KeyboardState.SwitchActions { @@ -26,8 +28,10 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions { // Argument for {@link KeyboardState#onCodeInput}. public static final boolean SINGLE = true; public static final boolean MULTI = false; - public static final boolean NO_AUTO_CAPS = false; - public static final boolean AUTO_CAPS = true; + public static final int CAP_MODE_OFF = + com.android.inputmethod.latin.Constants.TextUtils.CAP_MODE_OFF; + public static final int CAP_MODE_WORDS = TextUtils.CAP_MODE_WORDS; + public static final int CAP_MODE_CHARACTERS = TextUtils.CAP_MODE_CHARACTERS; public static final int CODE_SHIFT = Keyboard.CODE_SHIFT; public static final int CODE_SYMBOL = Keyboard.CODE_SWITCH_ALPHA_SYMBOL; @@ -45,9 +49,9 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions { private int mLayout = Constants.ALPHABET_UNSHIFTED; - private boolean mAutoCapsMode = Constants.NO_AUTO_CAPS; + private int mAutoCapsMode = Constants.CAP_MODE_OFF; // Following InputConnection's behavior. Simulating InputType.TYPE_TEXT_FLAG_CAP_WORDS. - private boolean mAutoCapsState = true; + private int mAutoCapsState = Constants.CAP_MODE_OFF; private boolean mIsInDoubleTapTimeout; private int mLongPressTimeoutCode; @@ -71,8 +75,9 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions { } } - public void setAutoCapsMode(boolean autoCaps) { + public void setAutoCapsMode(int autoCaps) { mAutoCapsMode = autoCaps; + mAutoCapsState = autoCaps; } public void expireDoubleTapTimeout() { @@ -116,7 +121,7 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions { @Override public void requestUpdatingShiftState() { - mState.onUpdateShiftState(mAutoCapsMode && mAutoCapsState); + mState.onUpdateShiftState(mAutoCapsState); } @Override @@ -158,7 +163,7 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions { } public void updateShiftState() { - mState.onUpdateShiftState(mAutoCapsMode && mAutoCapsState); + mState.onUpdateShiftState(mAutoCapsState); } public void loadKeyboard(String layoutSwitchBackSymbols) { @@ -181,10 +186,15 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions { } public void onCodeInput(int code, boolean isSinglePointer) { - if (Keyboard.isLetterCode(code)) { - mAutoCapsState = (code == Constants.CODE_AUTO_CAPS_TRIGGER); + if (mAutoCapsMode == Constants.CAP_MODE_WORDS) { + if (Keyboard.isLetterCode(code)) { + mAutoCapsState = (code == Constants.CODE_AUTO_CAPS_TRIGGER) + ? mAutoCapsMode : Constants.CAP_MODE_OFF; + } + } else { + mAutoCapsState = mAutoCapsMode; } - mState.onCodeInput(code, isSinglePointer, mAutoCapsMode && mAutoCapsState); + mState.onCodeInput(code, isSinglePointer, mAutoCapsState); } public void onCancelInput(boolean isSinglePointer) { -- cgit v1.2.3-83-g751a From 07cd1e1731a07ae014a78db59b518ff0dbce3e35 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Mon, 14 May 2012 09:41:39 -0700 Subject: switch ResearchLogger output to json. use multiple logging files, clean up internal nested class structure. multi-project commit with I1813b6710ef586d96cf8936662f58b870040d6e5 Bug: 6188932 Change-Id: I438790e28f74747c4c1a48a20c1942a0fd818b6c --- java/proguard.flags | 8 +- .../com/android/inputmethod/latin/LatinIME.java | 10 +- .../android/inputmethod/latin/ResearchLogger.java | 1110 ++++++++++---------- 3 files changed, 545 insertions(+), 583 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/proguard.flags b/java/proguard.flags index fd73e1242..2b638c665 100644 --- a/java/proguard.flags +++ b/java/proguard.flags @@ -37,13 +37,7 @@ } -keep class com.android.inputmethod.latin.ResearchLogger { - void setLogFileManager(...); - void clearAll(); - com.android.inputmethod.latin.ResearchLogger$LogFileManager getLogFileManager(); -} - --keep class com.android.inputmethod.latin.ResearchLogger$LogFileManager { - java.lang.String getContents(); + void flush(); } -keep class com.android.inputmethod.keyboard.KeyboardLayoutSet$Builder { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 28dcb1e89..345515e96 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -388,7 +388,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mPrefs = prefs; LatinImeLogger.init(this, prefs); if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.init(this, prefs); + ResearchLogger.getInstance().init(this, prefs); } InputMethodManagerCompatWrapper.init(this); SubtypeSwitcher.init(this); @@ -643,6 +643,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen + ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_WORDS) != 0)); } if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.getInstance().start(); ResearchLogger.latinIME_onStartInputViewInternal(editorInfo, mPrefs); } if (InputAttributes.inPrivateImeOptions(null, NO_MICROPHONE_COMPAT, editorInfo)) { @@ -724,6 +725,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen super.onFinishInput(); LatinImeLogger.commit(); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.getInstance().stop(); + } KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); if (inputView != null) inputView.closing(); @@ -1233,9 +1237,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mLastKeyTime = when; if (ProductionFlag.IS_EXPERIMENTAL) { - if (ResearchLogger.sIsLogging) { - ResearchLogger.getInstance().logKeyEvent(primaryCode, x, y); - } + ResearchLogger.latinIME_onCodeInput(primaryCode, x, y); } final KeyboardSwitcher switcher = mKeyboardSwitcher; diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index a46ed03af..063639c16 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -24,8 +24,8 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.Process; import android.os.SystemClock; -import android.preference.PreferenceManager; import android.text.TextUtils; +import android.util.JsonWriter; import android.util.Log; import android.view.MotionEvent; import android.view.inputmethod.CompletionInfo; @@ -36,19 +36,17 @@ import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.internal.KeyboardState; -import com.android.inputmethod.latin.EditingUtils.Range; import com.android.inputmethod.latin.define.ProductionFlag; import java.io.BufferedWriter; import java.io.File; -import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; -import java.io.PrintWriter; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.channels.FileChannel; -import java.nio.charset.Charset; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; import java.util.Map; import java.util.UUID; @@ -62,542 +60,486 @@ import java.util.UUID; */ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = ResearchLogger.class.getSimpleName(); - private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; - private static final String PREF_RESEARCH_LOGGER_UUID_STRING = "pref_research_logger_uuid"; private static final boolean DEBUG = false; + /* package */ static boolean sIsLogging = false; + private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; + private static final String FILENAME_PREFIX = "researchLog"; + private static final String FILENAME_SUFFIX = ".txt"; + private static final JsonWriter NULL_JSON_WRITER = new JsonWriter( + new OutputStreamWriter(new NullOutputStream())); + private static final SimpleDateFormat TIMESTAMP_DATEFORMAT = + new SimpleDateFormat("yyyyMMDDHHmmss", Locale.US); + + // constants related to specific log points private static final String WHITESPACE_SEPARATORS = " \t\n\r"; - - private static final ResearchLogger sInstance = new ResearchLogger(new LogFileManager()); private static final int MAX_INPUTVIEW_LENGTH_TO_CAPTURE = 8192; // must be >=1 - public static boolean sIsLogging = false; - /* package */ final Handler mLoggingHandler; - private InputMethodService mIms; - - // set when LatinIME should ignore a onUpdateSelection() callback that - // arises from operations in this class - private static boolean mLatinIMEExpectingUpdateSelection = false; - - /** - * Isolates management of files. This variable should never be null, but can be changed - * to support testing. - */ - /* package */ LogFileManager mLogFileManager; - - /** - * Manages the file(s) that stores the logs. - * - * Handles creation, deletion, and provides Readers, Writers, and InputStreams to access - * the logs. - */ - /* package */ static class LogFileManager { - public static final String RESEARCH_LOG_FILENAME_KEY = "RESEARCH_LOG_FILENAME"; + private static final String PREF_RESEARCH_LOGGER_UUID_STRING = "pref_research_logger_uuid"; - private static final String DEFAULT_FILENAME = "researchLog.txt"; - private static final long LOGFILE_PURGE_INTERVAL = 1000 * 60 * 60 * 24; + private static final ResearchLogger sInstance = new ResearchLogger(); + private HandlerThread mHandlerThread; + /* package */ Handler mLoggingHandler; + // to write to a different filename, e.g., for testing, set mFile before calling start() + private File mFilesDir; + /* package */ File mFile; + private JsonWriter mJsonWriter = NULL_JSON_WRITER; // should never be null - protected InputMethodService mIms; - protected File mFile; - protected PrintWriter mPrintWriter; + private int mLoggingState; + private static final int LOGGING_STATE_OFF = 0; + private static final int LOGGING_STATE_ON = 1; + private static final int LOGGING_STATE_STOPPING = 2; - /* package */ LogFileManager() { - } + // set when LatinIME should ignore an onUpdateSelection() callback that + // arises from operations in this class + private static boolean sLatinIMEExpectingUpdateSelection = false; - public void init(final InputMethodService ims) { - mIms = ims; + private static class NullOutputStream extends OutputStream { + /** {@inheritDoc} */ + @Override + public void write(byte[] buffer, int offset, int count) throws IOException { + // nop } - public synchronized void createLogFile() throws IOException { - createLogFile(DEFAULT_FILENAME); + /** {@inheritDoc} */ + @Override + public void write(byte[] buffer) throws IOException { + // nop } - public synchronized void createLogFile(final SharedPreferences prefs) - throws IOException { - final String filename = - prefs.getString(RESEARCH_LOG_FILENAME_KEY, DEFAULT_FILENAME); - createLogFile(filename); + @Override + public void write(int oneByte) { } + } - public synchronized void createLogFile(final String filename) - throws IOException { - if (mIms == null) { - final String msg = "InputMethodService is not configured. Logging is off."; - Log.w(TAG, msg); - throw new IOException(msg); - } - final File filesDir = mIms.getFilesDir(); - if (filesDir == null || !filesDir.exists()) { - final String msg = "Storage directory does not exist. Logging is off."; - Log.w(TAG, msg); - throw new IOException(msg); - } - close(); - final File file = new File(filesDir, filename); - mFile = file; - boolean append = true; - if (file.exists() && file.lastModified() + LOGFILE_PURGE_INTERVAL < - System.currentTimeMillis()) { - append = false; - } - mPrintWriter = new PrintWriter(new BufferedWriter(new FileWriter(file, append)), true); - } + private ResearchLogger() { + mLoggingState = LOGGING_STATE_OFF; + } - public synchronized boolean append(final String s) { - PrintWriter printWriter = mPrintWriter; - if (printWriter == null || !mFile.exists()) { - if (DEBUG) { - Log.w(TAG, "PrintWriter is null... attempting to create default log file"); - } - try { - createLogFile(); - printWriter = mPrintWriter; - } catch (IOException e) { - Log.w(TAG, "Failed to create log file. Not logging."); - return false; - } - } - printWriter.print(s); - printWriter.flush(); - return !printWriter.checkError(); - } + public static ResearchLogger getInstance() { + return sInstance; + } - public synchronized void reset() { - if (mPrintWriter != null) { - mPrintWriter.close(); - mPrintWriter = null; - if (DEBUG) { - Log.d(TAG, "logfile closed"); - } - } - if (mFile != null) { - mFile.delete(); - if (DEBUG) { - Log.d(TAG, "logfile deleted"); - } - mFile = null; + public void init(final InputMethodService ims, final SharedPreferences prefs) { + assert ims != null; + if (ims == null) { + Log.w(TAG, "IMS is null; logging is off"); + } else { + mFilesDir = ims.getFilesDir(); + if (mFilesDir == null || !mFilesDir.exists()) { + Log.w(TAG, "IME storage directory does not exist."); } } - - public synchronized void close() { - if (mPrintWriter != null) { - mPrintWriter.close(); - mPrintWriter = null; - mFile = null; - if (DEBUG) { - Log.d(TAG, "logfile closed"); - } - } + if (prefs != null) { + sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); + prefs.registerOnSharedPreferenceChangeListener(sInstance); } + } - /* package */ synchronized void flush() { - if (mPrintWriter != null) { - mPrintWriter.flush(); + public synchronized void start() { + Log.d(TAG, "start called"); + if (mFilesDir == null || !mFilesDir.exists()) { + Log.w(TAG, "IME storage directory does not exist. Cannot start logging."); + } else { + if (mHandlerThread == null || !mHandlerThread.isAlive()) { + mHandlerThread = new HandlerThread("ResearchLogger logging task", + Process.THREAD_PRIORITY_BACKGROUND); + mHandlerThread.start(); + mLoggingHandler = null; + mLoggingState = LOGGING_STATE_OFF; } - } - - /* package */ synchronized String getContents() { - final File file = mFile; - if (file == null) { - return ""; + if (mLoggingHandler == null) { + mLoggingHandler = new Handler(mHandlerThread.getLooper()); + mLoggingState = LOGGING_STATE_OFF; } - if (mPrintWriter != null) { - mPrintWriter.flush(); + if (mFile == null) { + final String timestampString = TIMESTAMP_DATEFORMAT.format(new Date()); + mFile = new File(mFilesDir, FILENAME_PREFIX + timestampString + FILENAME_SUFFIX); } - FileInputStream stream = null; - FileChannel fileChannel = null; - String s = ""; - try { - stream = new FileInputStream(file); - fileChannel = stream.getChannel(); - final ByteBuffer byteBuffer = ByteBuffer.allocate((int) file.length()); - fileChannel.read(byteBuffer); - byteBuffer.rewind(); - CharBuffer charBuffer = Charset.defaultCharset().decode(byteBuffer); - s = charBuffer.toString(); - } catch (IOException e) { - e.printStackTrace(); - } finally { + if (mLoggingState == LOGGING_STATE_OFF) { try { - if (fileChannel != null) { - fileChannel.close(); - } + mJsonWriter = new JsonWriter(new BufferedWriter(new FileWriter(mFile))); + mJsonWriter.setLenient(true); + mJsonWriter.beginArray(); + mLoggingState = LOGGING_STATE_ON; } catch (IOException e) { + Log.w(TAG, "cannot start JsonWriter"); + mJsonWriter = NULL_JSON_WRITER; e.printStackTrace(); - } finally { - try { - if (stream != null) { - stream.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } } } - return s; } } - private ResearchLogger(final LogFileManager logFileManager) { - final HandlerThread handlerThread = new HandlerThread("ResearchLogger logging task", - Process.THREAD_PRIORITY_BACKGROUND); - handlerThread.start(); - mLoggingHandler = new Handler(handlerThread.getLooper()); - mLogFileManager = logFileManager; - } - - public static ResearchLogger getInstance() { - return sInstance; - } - - public static void init(final InputMethodService ims, final SharedPreferences prefs) { - sInstance.initInternal(ims, prefs); - } - - /* package */ void initInternal(final InputMethodService ims, final SharedPreferences prefs) { - mIms = ims; - final LogFileManager logFileManager = mLogFileManager; - if (logFileManager != null) { - logFileManager.init(ims); + public synchronized void stop() { + Log.d(TAG, "stop called"); + if (mLoggingHandler != null && mLoggingState == LOGGING_STATE_ON) { + mLoggingState = LOGGING_STATE_STOPPING; + // put this in the Handler queue so pending writes are processed first. + mLoggingHandler.post(new Runnable() { + @Override + public void run() { + try { + Log.d(TAG, "closing jsonwriter"); + mJsonWriter.endArray(); + mJsonWriter.flush(); + mJsonWriter.close(); + } catch (IllegalStateException e1) { + // assume that this is just the json not being terminated properly. + // ignore + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + mJsonWriter = NULL_JSON_WRITER; + mFile = null; + mLoggingState = LOGGING_STATE_OFF; + if (DEBUG) { + Log.d(TAG, "logfile closed"); + } + Log.d(TAG, "finished stop(), notifying"); + synchronized (ResearchLogger.this) { + ResearchLogger.this.notify(); + } + } + }); try { - logFileManager.createLogFile(prefs); - } catch (IOException e) { + wait(); + } catch (InterruptedException e) { e.printStackTrace(); } } - if (prefs != null) { - sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); - prefs.registerOnSharedPreferenceChangeListener(this); - } } - /** - * Represents a category of logging events that share the same subfield structure. - */ - private static enum LogGroup { - MOTION_EVENT("m"), - KEY("k"), - CORRECTION("c"), - STATE_CHANGE("s"), - UNSTRUCTURED("u"); - - private final String mLogString; - - private LogGroup(final String logString) { - mLogString = logString; + /* package */ synchronized void flush() { + try { + mJsonWriter.flush(); + } catch (IOException e) { + e.printStackTrace(); } } - public void logMotionEvent(final int action, final long eventTime, final int id, - final int x, final int y, final float size, final float pressure) { - final String eventTag; - switch (action) { - case MotionEvent.ACTION_CANCEL: eventTag = "[Cancel]"; break; - case MotionEvent.ACTION_UP: eventTag = "[Up]"; break; - case MotionEvent.ACTION_DOWN: eventTag = "[Down]"; break; - case MotionEvent.ACTION_POINTER_UP: eventTag = "[PointerUp]"; break; - case MotionEvent.ACTION_POINTER_DOWN: eventTag = "[PointerDown]"; break; - case MotionEvent.ACTION_MOVE: eventTag = "[Move]"; break; - case MotionEvent.ACTION_OUTSIDE: eventTag = "[Outside]"; break; - default: eventTag = "[Action" + action + "]"; break; - } - if (!TextUtils.isEmpty(eventTag)) { - final StringBuilder sb = new StringBuilder(); - sb.append(eventTag); - sb.append('\t'); sb.append(eventTime); - sb.append('\t'); sb.append(id); - sb.append('\t'); sb.append(x); - sb.append('\t'); sb.append(y); - sb.append('\t'); sb.append(size); - sb.append('\t'); sb.append(pressure); - write(LogGroup.MOTION_EVENT, sb.toString()); + @Override + public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { + if (key == null || prefs == null) { + return; } + sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); } - public void logKeyEvent(final int code, final int x, final int y) { - final StringBuilder sb = new StringBuilder(); - sb.append(Keyboard.printableCode(code)); - sb.append('\t'); sb.append(x); - sb.append('\t'); sb.append(y); - write(LogGroup.KEY, sb.toString()); - } + private static final String CURRENT_TIME_KEY = "_ct"; + private static final String UPTIME_KEY = "_ut"; + private static final String EVENT_TYPE_KEY = "_ty"; + private static final Object[] EVENTKEYS_NULLVALUES = {}; - public void logCorrection(final String subgroup, final String before, final String after, - final int position) { - final StringBuilder sb = new StringBuilder(); - sb.append(subgroup); - sb.append('\t'); sb.append(before); - sb.append('\t'); sb.append(after); - sb.append('\t'); sb.append(position); - write(LogGroup.CORRECTION, sb.toString()); - } - - public void logStateChange(final String subgroup, final String details) { - write(LogGroup.STATE_CHANGE, subgroup + "\t" + details); - } - - public static class UnsLogGroup { - private static final boolean DEFAULT_ENABLED = true; - - private static final boolean KEYBOARDSTATE_ONCANCELINPUT_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_ONCODEINPUT_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_ONPRESSKEY_ENABLED = DEFAULT_ENABLED; - private static final boolean KEYBOARDSTATE_ONRELEASEKEY_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_COMMITCURRENTAUTOCORRECTION_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_COMMITTEXT_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_DELETESURROUNDINGTEXT_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_DOUBLESPACEAUTOPERIOD_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_ONDISPLAYCOMPLETIONS_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_ONWINDOWHIDDEN_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_ONUPDATESELECTION_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_PERFORMEDITORACTION_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION_ENABLED - = DEFAULT_ENABLED; - private static final boolean LATINIME_PICKPUNCTUATIONSUGGESTION_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_PICKSUGGESTIONMANUALLY_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_REVERTCOMMIT_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT_ENABLED - = DEFAULT_ENABLED; - private static final boolean LATINIME_REVERTSWAPPUNCTUATION_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_SENDKEYCODEPOINT_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT_ENABLED - = DEFAULT_ENABLED; - private static final boolean LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED = DEFAULT_ENABLED; - private static final boolean LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED - = DEFAULT_ENABLED; - private static final boolean LATINKEYBOARDVIEW_SETKEYBOARD_ENABLED = DEFAULT_ENABLED; - private static final boolean POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED - = DEFAULT_ENABLED; - private static final boolean POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED - = DEFAULT_ENABLED; - private static final boolean - POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED - = DEFAULT_ENABLED; - private static final boolean POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED = DEFAULT_ENABLED; - private static final boolean POINTERTRACKER_ONDOWNEVENT_ENABLED = DEFAULT_ENABLED; - private static final boolean POINTERTRACKER_ONMOVEEVENT_ENABLED = DEFAULT_ENABLED; - private static final boolean SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED - = DEFAULT_ENABLED; - private static final boolean SUGGESTIONSVIEW_SETSUGGESTIONS_ENABLED = DEFAULT_ENABLED; - } - - public static void logUnstructured(String logGroup, final String details) { - // TODO: improve performance by making entire class static and/or implementing natively - getInstance().write(LogGroup.UNSTRUCTURED, logGroup + "\t" + details); - } - - private void write(final LogGroup logGroup, final String log) { - // TODO: rewrite in native for better performance - mLoggingHandler.post(new Runnable() { - @Override - public void run() { - final long currentTime = System.currentTimeMillis(); - final long upTime = SystemClock.uptimeMillis(); - final StringBuilder builder = new StringBuilder(); - builder.append(currentTime); - builder.append('\t'); builder.append(upTime); - builder.append('\t'); builder.append(logGroup.mLogString); - builder.append('\t'); builder.append(log); - builder.append('\n'); - if (DEBUG) { - Log.d(TAG, "Write: " + '[' + logGroup.mLogString + ']' + log); - } - final String s = builder.toString(); - if (mLogFileManager.append(s)) { - // success - } else { - if (DEBUG) { - Log.w(TAG, "Unable to write to log."); - } - // perhaps logfile was deleted. try to recreate and relog. + /** + * Write a description of the event out to the ResearchLog. + * + * Runs in the background to avoid blocking the UI thread. + * + * @param keys an array containing a descriptive name for the event, followed by the keys + * @param values an array of values, either a String or Number. length should be one + * less than the keys array + */ + private synchronized void writeEvent(final String[] keys, final Object[] values) { + assert values.length + 1 == keys.length; + if (mLoggingState == LOGGING_STATE_ON) { + mLoggingHandler.post(new Runnable() { + @Override + public void run() { try { - mLogFileManager.createLogFile(PreferenceManager - .getDefaultSharedPreferences(mIms)); - mLogFileManager.append(s); + mJsonWriter.beginObject(); + mJsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis()); + mJsonWriter.name(UPTIME_KEY).value(SystemClock.uptimeMillis()); + mJsonWriter.name(EVENT_TYPE_KEY).value(keys[0]); + final int length = values.length; + for (int i = 0; i < length; i++) { + mJsonWriter.name(keys[i + 1]); + Object value = values[i]; + if (value instanceof String) { + mJsonWriter.value((String) value); + } else if (value instanceof Number) { + mJsonWriter.value((Number) value); + } else if (value instanceof Boolean) { + mJsonWriter.value((Boolean) value); + } else if (value instanceof CompletionInfo[]) { + CompletionInfo[] ci = (CompletionInfo[]) value; + mJsonWriter.beginArray(); + for (int j = 0; j < ci.length; j++) { + mJsonWriter.value(ci[j].toString()); + } + mJsonWriter.endArray(); + } else if (value instanceof SharedPreferences) { + SharedPreferences prefs = (SharedPreferences) value; + mJsonWriter.beginObject(); + for (Map.Entry entry : prefs.getAll().entrySet()) { + mJsonWriter.name(entry.getKey()); + final Object innerValue = entry.getValue(); + if (innerValue == null) { + mJsonWriter.nullValue(); + } else { + mJsonWriter.value(innerValue.toString()); + } + } + mJsonWriter.endObject(); + } else if (value instanceof Keyboard) { + Keyboard keyboard = (Keyboard) value; + mJsonWriter.beginArray(); + for (Key key : keyboard.mKeys) { + mJsonWriter.beginObject(); + mJsonWriter.name("code").value(key.mCode); + mJsonWriter.name("altCode").value(key.mAltCode); + mJsonWriter.name("x").value(key.mX); + mJsonWriter.name("y").value(key.mY); + mJsonWriter.name("w").value(key.mWidth); + mJsonWriter.name("h").value(key.mHeight); + mJsonWriter.endObject(); + } + mJsonWriter.endArray(); + } else if (value == null) { + mJsonWriter.nullValue(); + } else { + Log.w(TAG, "Unrecognized type to be logged: " + + (value == null ? "" : value.getClass().getName())); + mJsonWriter.nullValue(); + } + } + mJsonWriter.endObject(); } catch (IOException e) { e.printStackTrace(); + Log.w(TAG, "Error in JsonWriter; disabling logging"); + try { + mJsonWriter.close(); + } catch (IllegalStateException e1) { + // assume that this is just the json not being terminated properly. + // ignore + } catch (IOException e1) { + e1.printStackTrace(); + } finally { + mJsonWriter = NULL_JSON_WRITER; + } } } + }); + } + } + + private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT = { + "LATINKEYBOARDVIEW_PROCESSMOTIONEVENT", "action", "eventTime", "id", "x", "y", "size", + "pressure" + }; + public static void latinKeyboardView_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; + switch (action) { + case MotionEvent.ACTION_CANCEL: actionString = "CANCEL"; break; + case MotionEvent.ACTION_UP: actionString = "UP"; break; + case MotionEvent.ACTION_DOWN: actionString = "DOWN"; break; + case MotionEvent.ACTION_POINTER_UP: actionString = "POINTER_UP"; break; + case MotionEvent.ACTION_POINTER_DOWN: actionString = "POINTER_DOWN"; break; + case MotionEvent.ACTION_MOVE: actionString = "MOVE"; break; + case MotionEvent.ACTION_OUTSIDE: actionString = "OUTSIDE"; break; + default: actionString = "ACTION_" + action; break; } - }); + final float size = me.getSize(index); + final float pressure = me.getPressure(index); + final Object[] values = { + actionString, eventTime, id, x, y, size, pressure + }; + getInstance().writeEvent(EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT, values); + } } - public void clearAll() { - mLoggingHandler.post(new Runnable() { - @Override - public void run() { - if (DEBUG) { - Log.d(TAG, "Delete log file."); - } - mLogFileManager.reset(); - } - }); + private static final String[] EVENTKEYS_LATINIME_ONCODEINPUT = { + "LATINIME_ONCODEINPUT", "code", "x", "y" + }; + public static void latinIME_onCodeInput(final int code, final int x, final int y) { + final Object[] values = { + Keyboard.printableCode(code), x, y + }; + getInstance().writeEvent(EVENTKEYS_LATINIME_ONCODEINPUT, values); } - /* package */ LogFileManager getLogFileManager() { - return mLogFileManager; + private static final String[] EVENTKEYS_CORRECTION = { + "CORRECTION", "subgroup", "before", "after", "position" + }; + public static void logCorrection(final String subgroup, final String before, final String after, + final int position) { + final Object[] values = { + subgroup, before, after, position + }; + getInstance().writeEvent(EVENTKEYS_CORRECTION, values); } - @Override - public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { - if (key == null || prefs == null) { - return; - } - sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); + private static final String[] EVENTKEYS_STATECHANGE = { + "STATECHANGE", "subgroup", "details" + }; + public static void logStateChange(final String subgroup, final String details) { + final Object[] values = { + subgroup, details + }; + getInstance().writeEvent(EVENTKEYS_STATECHANGE, values); } + private static final String[] EVENTKEYS_KEYBOARDSTATE_ONCANCELINPUT = { + "KEYBOARDSTATE_ONCANCELINPUT", "isSinglePointer", "keyboardState" + }; public static void keyboardState_onCancelInput(final boolean isSinglePointer, final KeyboardState keyboardState) { - if (UnsLogGroup.KEYBOARDSTATE_ONCANCELINPUT_ENABLED) { - final String s = "onCancelInput: single=" + isSinglePointer + " " + keyboardState; - logUnstructured("KeyboardState_onCancelInput", s); - } + final Object[] values = { + isSinglePointer, keyboardState.toString() + }; + getInstance().writeEvent(EVENTKEYS_KEYBOARDSTATE_ONCANCELINPUT, values); } + private static final String[] EVENTKEYS_KEYBOARDSTATE_ONCODEINPUT = { + "KEYBOARDSTATE_ONCODEINPUT", "code", "isSinglePointer", "autoCaps", "keyboardState" + }; public static void keyboardState_onCodeInput( final int code, final boolean isSinglePointer, final boolean autoCaps, final KeyboardState keyboardState) { - if (UnsLogGroup.KEYBOARDSTATE_ONCODEINPUT_ENABLED) { - final String s = "onCodeInput: code=" + Keyboard.printableCode(code) - + " single=" + isSinglePointer - + " autoCaps=" + autoCaps + " " + keyboardState; - logUnstructured("KeyboardState_onCodeInput", s); - } + final Object[] values = { + Keyboard.printableCode(code), isSinglePointer, autoCaps, keyboardState.toString() + }; + getInstance().writeEvent(EVENTKEYS_KEYBOARDSTATE_ONCODEINPUT, values); } + private static final String[] EVENTKEYS_KEYBOARDSTATE_ONLONGPRESSTIMEOUT = { + "KEYBOARDSTATE_ONLONGPRESSTIMEOUT", "code", "keyboardState" + }; public static void keyboardState_onLongPressTimeout(final int code, final KeyboardState keyboardState) { - if (UnsLogGroup.KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED) { - final String s = "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " - + keyboardState; - logUnstructured("KeyboardState_onLongPressTimeout", s); - } + final Object[] values = { + Keyboard.printableCode(code), keyboardState.toString() + }; + getInstance().writeEvent(EVENTKEYS_KEYBOARDSTATE_ONLONGPRESSTIMEOUT, values); } + private static final String[] EVENTKEYS_KEYBOARDSTATE_ONPRESSKEY = { + "KEYBOARDSTATE_ONPRESSKEY", "code", "keyboardState" + }; public static void keyboardState_onPressKey(final int code, final KeyboardState keyboardState) { - if (UnsLogGroup.KEYBOARDSTATE_ONPRESSKEY_ENABLED) { - final String s = "onPressKey: code=" + Keyboard.printableCode(code) + " " - + keyboardState; - logUnstructured("KeyboardState_onPressKey", s); - } + final Object[] values = { + Keyboard.printableCode(code), keyboardState.toString() + }; + getInstance().writeEvent(EVENTKEYS_KEYBOARDSTATE_ONPRESSKEY, values); } + private static final String[] EVENTKEYS_KEYBOARDSTATE_ONRELEASEKEY = { + "KEYBOARDSTATE_ONRELEASEKEY", "code", "withSliding", "keyboardState" + }; public static void keyboardState_onReleaseKey(final KeyboardState keyboardState, final int code, final boolean withSliding) { - if (UnsLogGroup.KEYBOARDSTATE_ONRELEASEKEY_ENABLED) { - final String s = "onReleaseKey: code=" + Keyboard.printableCode(code) - + " sliding=" + withSliding + " " + keyboardState; - logUnstructured("KeyboardState_onReleaseKey", s); - } + final Object[] values = { + Keyboard.printableCode(code), withSliding, keyboardState.toString() + }; + getInstance().writeEvent(EVENTKEYS_KEYBOARDSTATE_ONRELEASEKEY, values); } + private static final String[] EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION = { + "LATINIME_COMMITCURRENTAUTOCORRECTION", "typedWord", "autoCorrection" + }; public static void latinIME_commitCurrentAutoCorrection(final String typedWord, final String autoCorrection) { - if (UnsLogGroup.LATINIME_COMMITCURRENTAUTOCORRECTION_ENABLED) { - if (typedWord.equals(autoCorrection)) { - getInstance().logCorrection("[----]", typedWord, autoCorrection, -1); - } else { - getInstance().logCorrection("[Auto]", typedWord, autoCorrection, -1); - } - } + final Object[] values = { + typedWord, autoCorrection + }; + getInstance().writeEvent(EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION, values); } + private static final String[] EVENTKEYS_LATINIME_COMMITTEXT = { + "LATINIME_COMMITTEXT", "typedWord" + }; public static void latinIME_commitText(final CharSequence typedWord) { - if (UnsLogGroup.LATINIME_COMMITTEXT_ENABLED) { - logUnstructured("LatinIME_commitText", typedWord.toString()); - } + final Object[] values = { + typedWord.toString() + }; + getInstance().writeEvent(EVENTKEYS_LATINIME_COMMITTEXT, values); } + private static final String[] EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT = { + "LATINIME_DELETESURROUNDINGTEXT", "length" + }; public static void latinIME_deleteSurroundingText(final int length) { - if (UnsLogGroup.LATINIME_DELETESURROUNDINGTEXT_ENABLED) { - logUnstructured("LatinIME_deleteSurroundingText", String.valueOf(length)); - } + final Object[] values = { + length + }; + getInstance().writeEvent(EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT, values); } + private static final String[] EVENTKEYS_LATINIME_DOUBLESPACEAUTOPERIOD = { + "LATINIME_DOUBLESPACEAUTOPERIOD" + }; public static void latinIME_doubleSpaceAutoPeriod() { - if (UnsLogGroup.LATINIME_DOUBLESPACEAUTOPERIOD_ENABLED) { - logUnstructured("LatinIME_doubleSpaceAutoPeriod", ""); - } + getInstance().writeEvent(EVENTKEYS_LATINIME_DOUBLESPACEAUTOPERIOD, EVENTKEYS_NULLVALUES); } + private static final String[] EVENTKEYS_LATINIME_ONDISPLAYCOMPLETIONS = { + "LATINIME_ONDISPLAYCOMPLETIONS", "applicationSpecifiedCompletions" + }; public static void latinIME_onDisplayCompletions( final CompletionInfo[] applicationSpecifiedCompletions) { - if (UnsLogGroup.LATINIME_ONDISPLAYCOMPLETIONS_ENABLED) { - final StringBuilder builder = new StringBuilder(); - builder.append("Received completions:"); - if (applicationSpecifiedCompletions != null) { - for (int i = 0; i < applicationSpecifiedCompletions.length; i++) { - builder.append(" #"); - builder.append(i); - builder.append(": "); - builder.append(applicationSpecifiedCompletions[i]); - builder.append("\n"); - } - } - logUnstructured("LatinIME_onDisplayCompletions", builder.toString()); - } + final Object[] values = { + applicationSpecifiedCompletions + }; + getInstance().writeEvent(EVENTKEYS_LATINIME_ONDISPLAYCOMPLETIONS, values); } /* package */ static boolean getAndClearLatinIMEExpectingUpdateSelection() { - boolean returnValue = mLatinIMEExpectingUpdateSelection; - mLatinIMEExpectingUpdateSelection = false; + boolean returnValue = sLatinIMEExpectingUpdateSelection; + sLatinIMEExpectingUpdateSelection = false; return returnValue; } + private static final String[] EVENTKEYS_LATINIME_ONWINDOWHIDDEN = { + "LATINIME_ONWINDOWHIDDEN", "isTextTruncated", "text" + }; public static void latinIME_onWindowHidden(final int savedSelectionStart, final int savedSelectionEnd, final InputConnection ic) { - if (UnsLogGroup.LATINIME_ONWINDOWHIDDEN_ENABLED) { - if (ic != null) { - ic.beginBatchEdit(); - ic.performContextMenuAction(android.R.id.selectAll); - CharSequence charSequence = ic.getSelectedText(0); - ic.setSelection(savedSelectionStart, savedSelectionEnd); - ic.endBatchEdit(); - mLatinIMEExpectingUpdateSelection = true; - if (TextUtils.isEmpty(charSequence)) { - logUnstructured("LatinIME_onWindowHidden", ""); - } 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); - logUnstructured("LatinIME_onWindowHidden", truncatedCharSequence.toString() - + ""); - } else { - logUnstructured("LatinIME_onWindowHidden", charSequence.toString()); + if (ic != null) { + ic.beginBatchEdit(); + ic.performContextMenuAction(android.R.id.selectAll); + CharSequence charSequence = ic.getSelectedText(0); + ic.setSelection(savedSelectionStart, savedSelectionEnd); + ic.endBatchEdit(); + sLatinIMEExpectingUpdateSelection = true; + Object[] values = new Object[2]; + if (TextUtils.isEmpty(charSequence)) { + values[0] = false; + values[1] = ""; + } 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); + values[0] = true; + values[1] = truncatedCharSequence.toString(); + } else { + values[0] = false; + values[1] = charSequence.toString(); } } + getInstance().writeEvent(EVENTKEYS_LATINIME_ONWINDOWHIDDEN, values); } } + private static final String[] EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL = { + "LATINIME_ONSTARTINPUTVIEWINTERNAL", "uuid", "packageName", "inputType", "imeOptions", + "display", "model", "prefs" + }; + public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo, final SharedPreferences prefs) { - if (UnsLogGroup.LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED) { - final StringBuilder builder = new StringBuilder(); - builder.append("onStartInputView: editorInfo:"); - builder.append("\tpackageName="); - builder.append(editorInfo.packageName); - builder.append("\tinputType="); - builder.append(Integer.toHexString(editorInfo.inputType)); - builder.append("\timeOptions="); - builder.append(Integer.toHexString(editorInfo.imeOptions)); - builder.append("\tdisplay="); builder.append(Build.DISPLAY); - builder.append("\tmodel="); builder.append(Build.MODEL); - for (Map.Entry entry : prefs.getAll().entrySet()) { - builder.append("\t" + entry.getKey()); - Object value = entry.getValue(); - builder.append("=" + ((value == null) ? "" : value.toString())); - } - builder.append("\tuuid="); builder.append(getUUID(prefs)); - logUnstructured("LatinIME_onStartInputViewInternal", builder.toString()); + if (editorInfo != null) { + final Object[] values = { + getUUID(prefs), editorInfo.packageName, Integer.toHexString(editorInfo.inputType), + Integer.toHexString(editorInfo.imeOptions), Build.DISPLAY, Build.MODEL, prefs + }; + getInstance().writeEvent(EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL, values); } } @@ -613,215 +555,239 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang return uuidString; } + private static final String[] EVENTKEYS_LATINIME_ONUPDATESELECTION = { + "LATINIME_ONUPDATESELECTION", "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 InputConnection connection) { - if (UnsLogGroup.LATINIME_ONUPDATESELECTION_ENABLED) { - final String s = "onUpdateSelection: oss=" + oldSelStart - + ", ose=" + oldSelEnd - + ", lss=" + lastSelectionStart - + ", lse=" + lastSelectionEnd - + ", nss=" + newSelStart - + ", nse=" + newSelEnd - + ", cs=" + composingSpanStart - + ", ce=" + composingSpanEnd - + ", eus=" + expectingUpdateSelection - + ", eusfl=" + expectingUpdateSelectionFromLogger - + ", context=\"" + EditingUtils.getWordRangeAtCursor(connection, - WHITESPACE_SEPARATORS, 1).mWord + "\""; - logUnstructured("LatinIME_onUpdateSelection", s); - } - } - + final Object[] values = { + lastSelectionStart, lastSelectionEnd, oldSelStart, oldSelEnd, newSelStart, + newSelEnd, composingSpanStart, composingSpanEnd, expectingUpdateSelection, + expectingUpdateSelectionFromLogger, + EditingUtils.getWordRangeAtCursor(connection, WHITESPACE_SEPARATORS, 1).mWord + }; + getInstance().writeEvent(EVENTKEYS_LATINIME_ONUPDATESELECTION, values); + } + + private static final String[] EVENTKEYS_LATINIME_PERFORMEDITORACTION = { + "LATINIME_PERFORMEDITORACTION", "imeActionNext" + }; public static void latinIME_performEditorAction(final int imeActionNext) { - if (UnsLogGroup.LATINIME_PERFORMEDITORACTION_ENABLED) { - logUnstructured("LatinIME_performEditorAction", String.valueOf(imeActionNext)); - } + final Object[] values = { + imeActionNext + }; + getInstance().writeEvent(EVENTKEYS_LATINIME_PERFORMEDITORACTION, values); } + private static final String[] EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION = { + "LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION", "index", "text", "x", "y" + }; public static void latinIME_pickApplicationSpecifiedCompletion(final int index, final CharSequence text, int x, int y) { - if (UnsLogGroup.LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION_ENABLED) { - final String s = String.valueOf(index) + '\t' + text + '\t' + x + '\t' + y; - logUnstructured("LatinIME_pickApplicationSpecifiedCompletion", s); - } + final Object[] values = { + index, text.toString(), x, y + }; + getInstance().writeEvent(EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION, values); } + private static final String[] EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY = { + "LATINIME_PICKSUGGESTIONMANUALLY", "replacedWord", "index", "suggestion", "x", "y" + }; public static void latinIME_pickSuggestionManually(final String replacedWord, final int index, CharSequence suggestion, int x, int y) { - if (UnsLogGroup.LATINIME_PICKSUGGESTIONMANUALLY_ENABLED) { - final String s = String.valueOf(index) + '\t' + suggestion + '\t' + x + '\t' + y; - logUnstructured("LatinIME_pickSuggestionManually", s); - } + final Object[] values = { + replacedWord, index, suggestion.toString(), x, y + }; + getInstance().writeEvent(EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY, values); } + private static final String[] EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION = { + "LATINIME_PUNCTUATIONSUGGESTION", "index", "suggestion", "x", "y" + }; public static void latinIME_punctuationSuggestion(final int index, final CharSequence suggestion, int x, int y) { - if (UnsLogGroup.LATINIME_PICKPUNCTUATIONSUGGESTION_ENABLED) { - final String s = String.valueOf(index) + '\t' + suggestion + '\t' + x + '\t' + y; - logUnstructured("LatinIME_pickPunctuationSuggestion", s); - } + final Object[] values = { + index, suggestion.toString(), x, y + }; + getInstance().writeEvent(EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION, values); } + private static final String[] EVENTKEYS_LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT = { + "LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT" + }; public static void latinIME_revertDoubleSpaceWhileInBatchEdit() { - if (UnsLogGroup.LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT_ENABLED) { - logUnstructured("LatinIME_revertDoubleSpaceWhileInBatchEdit", ""); - } + getInstance().writeEvent(EVENTKEYS_LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT, + EVENTKEYS_NULLVALUES); } + private static final String[] EVENTKEYS_LATINIME_REVERTSWAPPUNCTUATION = { + "LATINIME_REVERTSWAPPUNCTUATION" + }; public static void latinIME_revertSwapPunctuation() { - if (UnsLogGroup.LATINIME_REVERTSWAPPUNCTUATION_ENABLED) { - logUnstructured("LatinIME_revertSwapPunctuation", ""); - } + getInstance().writeEvent(EVENTKEYS_LATINIME_REVERTSWAPPUNCTUATION, EVENTKEYS_NULLVALUES); } + private static final String[] EVENTKEYS_LATINIME_SENDKEYCODEPOINT = { + "LATINIME_SENDKEYCODEPOINT", "code" + }; public static void latinIME_sendKeyCodePoint(final int code) { - if (UnsLogGroup.LATINIME_SENDKEYCODEPOINT_ENABLED) { - logUnstructured("LatinIME_sendKeyCodePoint", String.valueOf(code)); - } + final Object[] values = { + code + }; + getInstance().writeEvent(EVENTKEYS_LATINIME_SENDKEYCODEPOINT, values); } + private static final String[] EVENTKEYS_LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT = { + "LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT" + }; public static void latinIME_swapSwapperAndSpaceWhileInBatchEdit() { - if (UnsLogGroup.LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT_ENABLED) { - logUnstructured("latinIME_swapSwapperAndSpaceWhileInBatchEdit", ""); - } + getInstance().writeEvent(EVENTKEYS_LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT, + EVENTKEYS_NULLVALUES); } + private static final String[] EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW = { + "LATINIME_SWITCHTOKEYBOARDVIEW" + }; public static void latinIME_switchToKeyboardView() { - if (UnsLogGroup.LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED) { - final String s = "Switch to keyboard view."; - logUnstructured("LatinIME_switchToKeyboardView", s); - } + getInstance().writeEvent(EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW, EVENTKEYS_NULLVALUES); } + private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS = { + "LATINKEYBOARDVIEW_ONLONGPRESS" + }; public static void latinKeyboardView_onLongPress() { - if (UnsLogGroup.LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED) { - final String s = "long press detected"; - logUnstructured("LatinKeyboardView_onLongPress", s); - } - } - - public static void latinKeyboardView_processMotionEvent(MotionEvent me, int action, - long eventTime, int index, int id, int x, int y) { - if (UnsLogGroup.LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED) { - final float size = me.getSize(index); - final float pressure = me.getPressure(index); - if (action != MotionEvent.ACTION_MOVE) { - getInstance().logMotionEvent(action, eventTime, id, x, y, size, pressure); - } - } + getInstance().writeEvent(EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS, EVENTKEYS_NULLVALUES); } + private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD = { + "LATINKEYBOARDVIEW_SETKEYBOARD", "id", "tw", "th", "keys" + }; public static void latinKeyboardView_setKeyboard(final Keyboard keyboard) { - if (UnsLogGroup.LATINKEYBOARDVIEW_SETKEYBOARD_ENABLED) { - StringBuilder builder = new StringBuilder(); - builder.append("id="); - builder.append(keyboard.mId); - builder.append("\tw="); - builder.append(keyboard.mOccupiedWidth); - builder.append("\th="); - builder.append(keyboard.mOccupiedHeight); - builder.append("\tkeys=["); - boolean first = true; - for (Key key : keyboard.mKeys) { - if (first) { - first = false; - } else { - builder.append(","); - } - builder.append("{code:"); - builder.append(key.mCode); - builder.append(",altCode:"); - builder.append(key.mAltCode); - builder.append(",x:"); - builder.append(key.mX); - builder.append(",y:"); - builder.append(key.mY); - builder.append(",w:"); - builder.append(key.mWidth); - builder.append(",h:"); - builder.append(key.mHeight); - builder.append("}"); - } - builder.append("]"); - logUnstructured("LatinKeyboardView_setKeyboard", builder.toString()); + if (keyboard != null) { + final Object[] values = { + keyboard.mId.toString(), keyboard.mOccupiedWidth, keyboard.mOccupiedHeight, + keyboard + }; + getInstance().writeEvent(EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD, values); } } + private static final String[] EVENTKEYS_LATINIME_REVERTCOMMIT = { + "LATINIME_REVERTCOMMIT", "originallyTypedWord" + }; public static void latinIME_revertCommit(final String originallyTypedWord) { - if (UnsLogGroup.LATINIME_REVERTCOMMIT_ENABLED) { - logUnstructured("LatinIME_revertCommit", originallyTypedWord); - } + final Object[] values = { + originallyTypedWord + }; + getInstance().writeEvent(EVENTKEYS_LATINIME_REVERTCOMMIT, values); } + private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONCANCELINPUT = { + "POINTERTRACKER_CALLLISTENERONCANCELINPUT" + }; public static void pointerTracker_callListenerOnCancelInput() { - final String s = "onCancelInput"; - if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED) { - logUnstructured("PointerTracker_callListenerOnCancelInput", s); - } + getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONCANCELINPUT, + EVENTKEYS_NULLVALUES); } + private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONCODEINPUT = { + "POINTERTRACKER_CALLLISTENERONCODEINPUT", "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 (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED) { - final String s = "onCodeInput: " + Keyboard.printableCode(code) - + " text=" + key.mOutputText + " x=" + x + " y=" + y - + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode - + " enabled=" + key.isEnabled(); - logUnstructured("PointerTracker_callListenerOnCodeInput", s); + if (key != null) { + CharSequence outputText = key.mOutputText; + final Object[] values = { + Keyboard.printableCode(code), outputText == null ? "" : outputText.toString(), + x, y, ignoreModifierKey, altersCode, key.isEnabled() + }; + getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONCODEINPUT, values); } } + private static final String[] + EVENTKEYS_POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE = { + "POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE", "code", + "ignoreModifierKey", "isEnabled" + }; public static void pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange( final Key key, final boolean ignoreModifierKey) { - if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED) { - final String s = "onPress : " + KeyDetector.printableCode(key) - + " ignoreModifier=" + ignoreModifierKey - + " enabled=" + key.isEnabled(); - logUnstructured("PointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange", s); + if (key != null) { + final Object[] values = { + KeyDetector.printableCode(key), ignoreModifierKey, key.isEnabled() + }; + getInstance().writeEvent( + EVENTKEYS_POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE, + values); } } + private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONRELEASE = { + "POINTERTRACKER_CALLLISTENERONRELEASE", "code", "withSliding", "ignoreModifierKey", + "isEnabled" + }; public static void pointerTracker_callListenerOnRelease(final Key key, final int primaryCode, final boolean withSliding, final boolean ignoreModifierKey) { - if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED) { - final String s = "onRelease : " + Keyboard.printableCode(primaryCode) - + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey - + " enabled="+ key.isEnabled(); - logUnstructured("PointerTracker_callListenerOnRelease", s); + if (key != null) { + final Object[] values = { + Keyboard.printableCode(primaryCode), withSliding, ignoreModifierKey, + key.isEnabled() + }; + getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONRELEASE, values); } } + private static final String[] EVENTKEYS_POINTERTRACKER_ONDOWNEVENT = { + "POINTERTRACKER_ONDOWNEVENT", "deltaT", "distanceSquared" + }; public static void pointerTracker_onDownEvent(long deltaT, int distanceSquared) { - if (UnsLogGroup.POINTERTRACKER_ONDOWNEVENT_ENABLED) { - final String s = "onDownEvent: ignore potential noise: time=" + deltaT - + " distance=" + distanceSquared; - logUnstructured("PointerTracker_onDownEvent", s); - } + final Object[] values = { + deltaT, distanceSquared + }; + getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_ONDOWNEVENT, values); } + private static final String[] EVENTKEYS_POINTERTRACKER_ONMOVEEVENT = { + "POINTERTRACKER_ONMOVEEVENT", "x", "y", "lastX", "lastY" + }; public static void pointerTracker_onMoveEvent(final int x, final int y, final int lastX, final int lastY) { - if (UnsLogGroup.POINTERTRACKER_ONMOVEEVENT_ENABLED) { - final String s = String.format("onMoveEvent: sudden move is translated to " - + "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y); - logUnstructured("PointerTracker_onMoveEvent", s); - } + final Object[] values = { + x, y, lastX, lastY + }; + getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_ONMOVEEVENT, values); } + private static final String[] EVENTKEYS_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT = { + "SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT", "motionEvent" + }; public static void suddenJumpingTouchEventHandler_onTouchEvent(final MotionEvent me) { - if (UnsLogGroup.SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED) { - final String s = "onTouchEvent: ignore sudden jump " + me; - logUnstructured("SuddenJumpingTouchEventHandler_onTouchEvent", s); - } - } - - public static void suggestionsView_setSuggestions(final SuggestedWords mSuggestedWords) { - if (UnsLogGroup.SUGGESTIONSVIEW_SETSUGGESTIONS_ENABLED) { - logUnstructured("SuggestionsView_setSuggestions", mSuggestedWords.toString()); + if (me != null) { + final Object[] values = { + me.toString() + }; + getInstance().writeEvent(EVENTKEYS_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT, + values); + } + } + + private static final String[] EVENTKEYS_SUGGESTIONSVIEW_SETSUGGESTIONS = { + "SUGGESTIONSVIEW_SETSUGGESTIONS", "suggestedWords" + }; + public static void suggestionsView_setSuggestions(final SuggestedWords suggestedWords) { + if (suggestedWords != null) { + final Object[] values = { + suggestedWords.toString() + }; + getInstance().writeEvent(EVENTKEYS_SUGGESTIONSVIEW_SETSUGGESTIONS, values); } } } -- cgit v1.2.3-83-g751a From 93ebf74bae44728e0d5f7e738ea28376187a876e Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 25 May 2012 19:04:54 +0900 Subject: Clean up some compiler warnings Change-Id: I604da15e65fc3cf807ec4033df4e4cd5ef0196fc --- java/src/com/android/inputmethod/keyboard/PointerTracker.java | 6 ------ java/src/com/android/inputmethod/latin/ContactsDictionary.java | 1 + java/src/com/android/inputmethod/latin/Dictionary.java | 2 +- java/src/com/android/inputmethod/latin/DictionaryFactory.java | 1 - java/src/com/android/inputmethod/latin/ExpandableDictionary.java | 3 ++- java/src/com/android/inputmethod/latin/ResearchLogger.java | 2 +- java/src/com/android/inputmethod/latin/UserDictionary.java | 1 + .../android/inputmethod/latin/makedict/BinaryDictInputOutput.java | 8 ++++---- .../com/android/inputmethod/latin/makedict/FusionDictionary.java | 8 +++++--- .../inputmethod/latin/spellcheck/AndroidSpellCheckerService.java | 4 ---- 10 files changed, 15 insertions(+), 21 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 6ad854d1b..59f53fc21 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -452,12 +452,6 @@ public class PointerTracker { return newKey; } - private Key onUpKey(int x, int y, long eventTime) { - mUpTime = eventTime; - mCurrentKey = null; - return onMoveKeyInternal(x, y); - } - public void processMotionEvent(int action, int x, int y, long eventTime, KeyEventHandler handler) { switch (action) { diff --git a/java/src/com/android/inputmethod/latin/ContactsDictionary.java b/java/src/com/android/inputmethod/latin/ContactsDictionary.java index 2f3395245..c9b8d6eb1 100644 --- a/java/src/com/android/inputmethod/latin/ContactsDictionary.java +++ b/java/src/com/android/inputmethod/latin/ContactsDictionary.java @@ -34,6 +34,7 @@ import com.android.inputmethod.keyboard.Keyboard; * * @deprecated Use {@link ContactsBinaryDictionary}. */ +@Deprecated public class ContactsDictionary extends ExpandableDictionary { private static final String[] PROJECTION = { diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java index 1ec678f7f..231e9ab81 100644 --- a/java/src/com/android/inputmethod/latin/Dictionary.java +++ b/java/src/com/android/inputmethod/latin/Dictionary.java @@ -33,7 +33,7 @@ public abstract class Dictionary { /** * Interface to be implemented by classes requesting words to be fetched from the dictionary. - * @see #getWords(WordComposer, WordCallback, ProximityInfo) + * @see #getWords(WordComposer, CharSequence, WordCallback, ProximityInfo) */ public interface WordCallback { /** diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 4cd1b3883..a22d73af7 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -89,7 +89,6 @@ public class DictionaryFactory { /** * Initializes a dictionary from a raw resource file * @param context application context for reading resources - * @param resId the resource containing the raw binary dictionary * @param locale the locale to use for the resource * @return an initialized instance of BinaryDictionary */ diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java index dd9c57e0c..6c457afd2 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -309,7 +309,8 @@ public class ExpandableDictionary extends Dictionary { * @param word the word to insert, as an array of code points * @param depth the depth of the node in the tree * @param finalFreq the frequency for this word - * @return whether there is still space for more words. {@see Dictionary.WordCallback#addWord}. + * @return whether there is still space for more words. + * @see Dictionary.WordCallback#addWord(char[], int, int, int, int, int) */ private boolean addWordAndShortcutsFromNode(final Node node, final char[] word, final int depth, final int finalFreq, final WordCallback callback) { diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index aa979a66f..66d6d58b1 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -54,7 +54,7 @@ import java.util.Map; * 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.IS_EXPERIMENTAL}. + * This functionality is off by default. See {@link ProductionFlag#IS_EXPERIMENTAL}. */ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = ResearchLogger.class.getSimpleName(); diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java index 81e2fdce4..c1efadd44 100644 --- a/java/src/com/android/inputmethod/latin/UserDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserDictionary.java @@ -35,6 +35,7 @@ import java.util.Arrays; * * @deprecated Use {@link UserBinaryDictionary}. */ +@Deprecated public class UserDictionary extends ExpandableDictionary { // TODO: use Words.SHORTCUT when it's public in the SDK diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 563f8a99b..89c59f809 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -882,9 +882,9 @@ public class BinaryDictInputOutput { final int indexOfShortcutByteSize = index; index += GROUP_SHORTCUT_LIST_SIZE_SIZE; groupAddress += GROUP_SHORTCUT_LIST_SIZE_SIZE; - final Iterator shortcutIterator = group.mShortcutTargets.iterator(); + final Iterator shortcutIterator = group.mShortcutTargets.iterator(); while (shortcutIterator.hasNext()) { - final WeightedString target = (WeightedString)shortcutIterator.next(); + final WeightedString target = shortcutIterator.next(); ++groupAddress; int shortcutFlags = makeShortcutFlags(shortcutIterator.hasNext(), target.mFrequency); @@ -902,9 +902,9 @@ public class BinaryDictInputOutput { } // Write bigrams if (null != group.mBigrams) { - final Iterator bigramIterator = group.mBigrams.iterator(); + final Iterator bigramIterator = group.mBigrams.iterator(); while (bigramIterator.hasNext()) { - final WeightedString bigram = (WeightedString)bigramIterator.next(); + final WeightedString bigram = bigramIterator.next(); final CharGroup target = FusionDictionary.findWordInTree(dict.mRoot, bigram.mWord); final int addressOfBigram = target.mCachedAddress; diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java index c467ef7d4..8b53c9427 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java +++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java @@ -296,7 +296,6 @@ public class FusionDictionary implements Iterable { * @param word the word to add. * @param frequency the frequency of the word, in the range [0..255]. * @param shortcutTargets a list of shortcut targets for this word, or null. - * @param bigrams a list of bigrams, or null. */ public void add(final String word, final int frequency, final ArrayList shortcutTargets) { @@ -435,6 +434,8 @@ public class FusionDictionary implements Iterable { } } + private static int ARRAYS_ARE_EQUAL = 0; + /** * Custom comparison of two int arrays taken to contain character codes. * @@ -450,7 +451,6 @@ public class FusionDictionary implements Iterable { * @param dstOffset the offset in the right-hand side string. * @return the index at which the strings differ, or ARRAYS_ARE_EQUAL = 0 if they don't. */ - private static int ARRAYS_ARE_EQUAL = 0; private static int compareArrays(final int[] src, final int[] dst, int dstOffset) { // We do NOT test the first char, because we come from a method that already // tested it. @@ -469,6 +469,7 @@ public class FusionDictionary implements Iterable { * This comparator imposes orderings that are inconsistent with equals. */ static private class CharGroupComparator implements java.util.Comparator { + @Override public int compare(CharGroup c1, CharGroup c2) { if (c1.mChars[0] == c2.mChars[0]) return 0; return c1.mChars[0] < c2.mChars[0] ? -1 : 1; @@ -487,6 +488,8 @@ public class FusionDictionary implements Iterable { return result >= 0 ? result : -result - 1; } + private static int CHARACTER_NOT_FOUND = -1; + /** * Find the index of a char in a node, if it exists. * @@ -494,7 +497,6 @@ public class FusionDictionary implements Iterable { * @param character the character to search for. * @return the position of the character if it's there, or CHARACTER_NOT_FOUND = -1 else. */ - private static int CHARACTER_NOT_FOUND = -1; private static int findIndexOfChar(final Node node, int character) { final int insertionIndex = findInsertionIndex(node, character); if (node.mData.size() <= insertionIndex) return CHARACTER_NOT_FOUND; diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index aa3250185..0e3bf8011 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -499,10 +499,6 @@ public class AndroidSpellCheckerService extends SpellCheckerService } mUnigramSuggestionsInfoCache.put(query, new SuggestionsParams(suggestions, flags)); } - - public void remove(String key) { - mUnigramSuggestionsInfoCache.remove(key); - } } AndroidSpellCheckerSession(final AndroidSpellCheckerService service) { -- cgit v1.2.3-83-g751a From 86fcadde5d1ca69e4d93dc7cf5e72c763a32ac84 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Tue, 29 May 2012 09:33:09 -0700 Subject: Fixes to json output - booleans and numbers in SharedPreferences not quoted as strings - removed redundant logging from KeyboardState - json output for KeyboardId - remove unnecessary logging of LatinImeLogger.onStartView() and PointerTracker checking keyboardlayoutchange - fix to day-of-month part of uuid Multi-project commit with Idb8f190214f852ab2b58df49f9e514dc7fcbecbb Bug: 6188932 Change-Id: I67b4a0b34aa26c2804e2b3ee2136614f0ec8181a --- .../inputmethod/keyboard/PointerTracker.java | 4 - .../keyboard/internal/KeyboardState.java | 15 -- .../android/inputmethod/latin/ResearchLogger.java | 159 ++++++++------------- 3 files changed, 63 insertions(+), 115 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 59f53fc21..57f633ccc 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -237,10 +237,6 @@ public class PointerTracker { + " ignoreModifier=" + ignoreModifierKey + " enabled=" + key.isEnabled()); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange(key, - ignoreModifierKey); - } if (ignoreModifierKey) { return false; } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index c85122ad3..b63343a50 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -302,9 +302,6 @@ public class KeyboardState { Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code) + " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onPressKey(code, this); - } if (code == Keyboard.CODE_SHIFT) { onPressShift(); } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { @@ -337,9 +334,6 @@ public class KeyboardState { Log.d(TAG, "onReleaseKey: code=" + Keyboard.printableCode(code) + " sliding=" + withSliding + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onReleaseKey(this, code, withSliding); - } if (code == Keyboard.CODE_SHIFT) { onReleaseShift(withSliding); } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { @@ -371,9 +365,6 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onLongPressTimeout(code, this); - } if (mIsAlphabetMode && code == Keyboard.CODE_SHIFT) { if (mAlphabetShiftState.isShiftLocked()) { setShiftLocked(false); @@ -510,9 +501,6 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onCancelInput: single=" + isSinglePointer + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onCancelInput(isSinglePointer, this); - } // Switch back to the previous keyboard mode if the user cancels sliding input. if (isSinglePointer) { if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) { @@ -544,9 +532,6 @@ public class KeyboardState { + " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this); } - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.keyboardState_onCodeInput(code, isSinglePointer, autoCaps, this); - } switch (mSwitchState) { case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index e7d044667..e792d4733 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -16,6 +16,8 @@ package com.android.inputmethod.latin; +import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET; + import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.inputmethodservice.InputMethodService; @@ -35,7 +37,8 @@ import android.view.inputmethod.InputConnection; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.keyboard.internal.KeyboardState; +import com.android.inputmethod.keyboard.KeyboardId; +import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.define.ProductionFlag; import java.io.BufferedWriter; @@ -68,7 +71,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final JsonWriter NULL_JSON_WRITER = new JsonWriter( new OutputStreamWriter(new NullOutputStream())); private static final SimpleDateFormat TIMESTAMP_DATEFORMAT = - new SimpleDateFormat("yyyyMMDDHHmmss", Locale.US); + new SimpleDateFormat("yyyyMMddHHmmss", Locale.US); // constants related to specific log points private static final String WHITESPACE_SEPARATORS = " \t\n\r"; @@ -275,15 +278,19 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object innerValue = entry.getValue(); if (innerValue == null) { mJsonWriter.nullValue(); + } else if (innerValue instanceof Boolean) { + mJsonWriter.value((Boolean) innerValue); + } else if (innerValue instanceof Number) { + mJsonWriter.value((Number) innerValue); } else { mJsonWriter.value(innerValue.toString()); } } mJsonWriter.endObject(); - } else if (value instanceof Keyboard) { - Keyboard keyboard = (Keyboard) value; + } else if (value instanceof Key[]) { + Key[] keys = (Key[]) value; mJsonWriter.beginArray(); - for (Key key : keyboard.mKeys) { + for (Key key : keys) { mJsonWriter.beginObject(); mJsonWriter.name("code").value(key.mCode); mJsonWriter.name("altCode").value(key.mAltCode); @@ -294,6 +301,29 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mJsonWriter.endObject(); } mJsonWriter.endArray(); + } else if (value instanceof SuggestedWords) { + SuggestedWords words = (SuggestedWords) value; + mJsonWriter.beginObject(); + mJsonWriter.name("typedWordValid").value(words.mTypedWordValid); + mJsonWriter.name("hasAutoCorrectionCandidate") + .value(words.mHasAutoCorrectionCandidate); + mJsonWriter.name("isPunctuationSuggestions") + .value(words.mIsPunctuationSuggestions); + mJsonWriter.name("allowsToBeAutoCorrected") + .value(words.mAllowsToBeAutoCorrected); + mJsonWriter.name("isObsoleteSuggestions") + .value(words.mIsObsoleteSuggestions); + mJsonWriter.name("isPrediction") + .value(words.mIsPrediction); + mJsonWriter.name("words"); + mJsonWriter.beginArray(); + final int size = words.size(); + for (int j = 0; j < size; j++) { + SuggestedWordInfo wordInfo = words.getWordInfo(j); + mJsonWriter.value(wordInfo.toString()); + } + mJsonWriter.endArray(); + mJsonWriter.endObject(); } else if (value == null) { mJsonWriter.nullValue(); } else { @@ -370,72 +400,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang getInstance().writeEvent(EVENTKEYS_CORRECTION, values); } - private static final String[] EVENTKEYS_STATECHANGE = { - "STATECHANGE", "subgroup", "details" - }; - public static void logStateChange(final String subgroup, final String details) { - final Object[] values = { - subgroup, details - }; - getInstance().writeEvent(EVENTKEYS_STATECHANGE, values); - } - - private static final String[] EVENTKEYS_KEYBOARDSTATE_ONCANCELINPUT = { - "KEYBOARDSTATE_ONCANCELINPUT", "isSinglePointer", "keyboardState" - }; - public static void keyboardState_onCancelInput(final boolean isSinglePointer, - final KeyboardState keyboardState) { - final Object[] values = { - isSinglePointer, keyboardState.toString() - }; - getInstance().writeEvent(EVENTKEYS_KEYBOARDSTATE_ONCANCELINPUT, values); - } - - private static final String[] EVENTKEYS_KEYBOARDSTATE_ONCODEINPUT = { - "KEYBOARDSTATE_ONCODEINPUT", "code", "isSinglePointer", "autoCaps", "keyboardState" - }; - public static void keyboardState_onCodeInput( - final int code, final boolean isSinglePointer, final int autoCaps, - final KeyboardState keyboardState) { - final Object[] values = { - Keyboard.printableCode(code), isSinglePointer, autoCaps, keyboardState.toString() - }; - getInstance().writeEvent(EVENTKEYS_KEYBOARDSTATE_ONCODEINPUT, values); - } - - private static final String[] EVENTKEYS_KEYBOARDSTATE_ONLONGPRESSTIMEOUT = { - "KEYBOARDSTATE_ONLONGPRESSTIMEOUT", "code", "keyboardState" - }; - public static void keyboardState_onLongPressTimeout(final int code, - final KeyboardState keyboardState) { - final Object[] values = { - Keyboard.printableCode(code), keyboardState.toString() - }; - getInstance().writeEvent(EVENTKEYS_KEYBOARDSTATE_ONLONGPRESSTIMEOUT, values); - } - - private static final String[] EVENTKEYS_KEYBOARDSTATE_ONPRESSKEY = { - "KEYBOARDSTATE_ONPRESSKEY", "code", "keyboardState" - }; - public static void keyboardState_onPressKey(final int code, - final KeyboardState keyboardState) { - final Object[] values = { - Keyboard.printableCode(code), keyboardState.toString() - }; - getInstance().writeEvent(EVENTKEYS_KEYBOARDSTATE_ONPRESSKEY, values); - } - - private static final String[] EVENTKEYS_KEYBOARDSTATE_ONRELEASEKEY = { - "KEYBOARDSTATE_ONRELEASEKEY", "code", "withSliding", "keyboardState" - }; - public static void keyboardState_onReleaseKey(final KeyboardState keyboardState, final int code, - final boolean withSliding) { - final Object[] values = { - Keyboard.printableCode(code), withSliding, keyboardState.toString() - }; - getInstance().writeEvent(EVENTKEYS_KEYBOARDSTATE_ONRELEASEKEY, values); - } - private static final String[] EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION = { "LATINIME_COMMITCURRENTAUTOCORRECTION", "typedWord", "autoCorrection" }; @@ -529,7 +493,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final String[] EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL = { "LATINIME_ONSTARTINPUTVIEWINTERNAL", "uuid", "packageName", "inputType", "imeOptions", - "display", "model", "prefs" + "fieldId", "display", "model", "prefs" }; public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo, @@ -537,7 +501,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang if (editorInfo != null) { final Object[] values = { getUUID(prefs), editorInfo.packageName, Integer.toHexString(editorInfo.inputType), - Integer.toHexString(editorInfo.imeOptions), Build.DISPLAY, Build.MODEL, prefs + Integer.toHexString(editorInfo.imeOptions), editorInfo.fieldId, Build.DISPLAY, + Build.MODEL, prefs }; getInstance().writeEvent(EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL, values); } @@ -558,7 +523,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final String[] EVENTKEYS_LATINIME_ONUPDATESELECTION = { "LATINIME_ONUPDATESELECTION", "lastSelectionStart", "lastSelectionEnd", "oldSelStart", "oldSelEnd", "newSelStart", "newSelEnd", "composingSpanStart", "composingSpanEnd", - "expectingUpdateSelection", "expectingUpdateSelectionFromLogger", "context" + "expectingUpdateSelection", "expectingUpdateSelectionFromLogger", "context" }; public static void latinIME_onUpdateSelection(final int lastSelectionStart, @@ -666,14 +631,33 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD = { - "LATINKEYBOARDVIEW_SETKEYBOARD", "id", "tw", "th", "keys" + "LATINKEYBOARDVIEW_SETKEYBOARD", "elementId", "locale", "orientation", "width", + "modeName", "action", "navigateNext", "navigatePrevious", "clobberSettingsKey", + "passwordInput", "shortcutKeyEnabled", "hasShortcutKey", "languageSwitchKeyEnabled", + "isMultiLine", "tw", "th", "keys" }; public static void latinKeyboardView_setKeyboard(final Keyboard keyboard) { if (keyboard != null) { + final KeyboardId kid = keyboard.mId; final Object[] values = { - keyboard.mId.toString(), keyboard.mOccupiedWidth, keyboard.mOccupiedHeight, - keyboard - }; + 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, + kid.passwordInput(), + kid.mShortcutKeyEnabled, + kid.mHasShortcutKey, + kid.mLanguageSwitchKeyEnabled, + kid.isMultiLine(), + keyboard.mOccupiedWidth, + keyboard.mOccupiedHeight, + keyboard.mKeys + }; getInstance().writeEvent(EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD, values); } } @@ -713,23 +697,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - private static final String[] - EVENTKEYS_POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE = { - "POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE", "code", - "ignoreModifierKey", "isEnabled" - }; - public static void pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange( - final Key key, final boolean ignoreModifierKey) { - if (key != null) { - final Object[] values = { - KeyDetector.printableCode(key), ignoreModifierKey, key.isEnabled() - }; - getInstance().writeEvent( - EVENTKEYS_POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE, - values); - } - } - private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONRELEASE = { "POINTERTRACKER_CALLLISTENERONRELEASE", "code", "withSliding", "ignoreModifierKey", "isEnabled" @@ -785,7 +752,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang public static void suggestionsView_setSuggestions(final SuggestedWords suggestedWords) { if (suggestedWords != null) { final Object[] values = { - suggestedWords.toString() + suggestedWords }; getInstance().writeEvent(EVENTKEYS_SUGGESTIONSVIEW_SETSUGGESTIONS, values); } -- cgit v1.2.3-83-g751a From 58caa775a700e99d18cdca922861f1882bf8d1f4 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Thu, 31 May 2012 14:19:38 -0700 Subject: Include version number in log output. Bug: 6188932 Change-Id: I1039a3ad317d207599f30fe578bdf814c80d6852 --- java/src/com/android/inputmethod/latin/ResearchLogger.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index e792d4733..1e905e662 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -65,6 +65,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final String TAG = ResearchLogger.class.getSimpleName(); private static final boolean DEBUG = false; /* package */ static boolean sIsLogging = false; + private static final int OUTPUT_FORMAT_VERSION = 1; private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; private static final String FILENAME_PREFIX = "researchLog"; private static final String FILENAME_SUFFIX = ".txt"; @@ -493,16 +494,15 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final String[] EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL = { "LATINIME_ONSTARTINPUTVIEWINTERNAL", "uuid", "packageName", "inputType", "imeOptions", - "fieldId", "display", "model", "prefs" + "fieldId", "display", "model", "prefs", "outputFormatVersion" }; - public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo, final SharedPreferences prefs) { if (editorInfo != null) { final Object[] values = { getUUID(prefs), editorInfo.packageName, Integer.toHexString(editorInfo.inputType), Integer.toHexString(editorInfo.imeOptions), editorInfo.fieldId, Build.DISPLAY, - Build.MODEL, prefs + Build.MODEL, prefs, OUTPUT_FORMAT_VERSION }; getInstance().writeEvent(EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL, values); } @@ -525,7 +525,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang "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, -- cgit v1.2.3-83-g751a From f739119f3ff54d7c37b67b873373b236a45e47e4 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Mon, 4 Jun 2012 11:55:33 -0700 Subject: Change constants in ResearchLogger Bug: 6188932 Change-Id: I3c6a3fb3e8fb139e16322e544f12bc3294cdaf1c --- .../android/inputmethod/latin/ResearchLogger.java | 60 +++++++++++----------- 1 file changed, 30 insertions(+), 30 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 1e905e662..16285091b 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -354,7 +354,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT = { - "LATINKEYBOARDVIEW_PROCESSMOTIONEVENT", "action", "eventTime", "id", "x", "y", "size", + "LatinKeyboardViewProcessMotionEvent", "action", "eventTime", "id", "x", "y", "size", "pressure" }; public static void latinKeyboardView_processMotionEvent(final MotionEvent me, final int action, @@ -381,7 +381,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_ONCODEINPUT = { - "LATINIME_ONCODEINPUT", "code", "x", "y" + "LatinIMEOnCodeInput", "code", "x", "y" }; public static void latinIME_onCodeInput(final int code, final int x, final int y) { final Object[] values = { @@ -391,7 +391,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_CORRECTION = { - "CORRECTION", "subgroup", "before", "after", "position" + "LogCorrection", "subgroup", "before", "after", "position" }; public static void logCorrection(final String subgroup, final String before, final String after, final int position) { @@ -402,7 +402,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION = { - "LATINIME_COMMITCURRENTAUTOCORRECTION", "typedWord", "autoCorrection" + "LatinIMECommitCurrentAutoCorrection", "typedWord", "autoCorrection" }; public static void latinIME_commitCurrentAutoCorrection(final String typedWord, final String autoCorrection) { @@ -413,7 +413,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_COMMITTEXT = { - "LATINIME_COMMITTEXT", "typedWord" + "LatinIMECommitText", "typedWord" }; public static void latinIME_commitText(final CharSequence typedWord) { final Object[] values = { @@ -423,7 +423,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT = { - "LATINIME_DELETESURROUNDINGTEXT", "length" + "LatinIMEDeleteSurroundingText", "length" }; public static void latinIME_deleteSurroundingText(final int length) { final Object[] values = { @@ -433,14 +433,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_DOUBLESPACEAUTOPERIOD = { - "LATINIME_DOUBLESPACEAUTOPERIOD" + "LatinIMEDoubleSpaceAutoPeriod" }; public static void latinIME_doubleSpaceAutoPeriod() { getInstance().writeEvent(EVENTKEYS_LATINIME_DOUBLESPACEAUTOPERIOD, EVENTKEYS_NULLVALUES); } private static final String[] EVENTKEYS_LATINIME_ONDISPLAYCOMPLETIONS = { - "LATINIME_ONDISPLAYCOMPLETIONS", "applicationSpecifiedCompletions" + "LatinIMEOnDisplayCompletions", "applicationSpecifiedCompletions" }; public static void latinIME_onDisplayCompletions( final CompletionInfo[] applicationSpecifiedCompletions) { @@ -457,7 +457,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_ONWINDOWHIDDEN = { - "LATINIME_ONWINDOWHIDDEN", "isTextTruncated", "text" + "LatinIMEOnWindowHidden", "isTextTruncated", "text" }; public static void latinIME_onWindowHidden(final int savedSelectionStart, final int savedSelectionEnd, final InputConnection ic) { @@ -493,7 +493,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL = { - "LATINIME_ONSTARTINPUTVIEWINTERNAL", "uuid", "packageName", "inputType", "imeOptions", + "LatinIMEOnStartInputViewInternal", "uuid", "packageName", "inputType", "imeOptions", "fieldId", "display", "model", "prefs", "outputFormatVersion" }; public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo, @@ -521,7 +521,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_ONUPDATESELECTION = { - "LATINIME_ONUPDATESELECTION", "lastSelectionStart", "lastSelectionEnd", "oldSelStart", + "LatinIMEOnUpdateSelection", "lastSelectionStart", "lastSelectionEnd", "oldSelStart", "oldSelEnd", "newSelStart", "newSelEnd", "composingSpanStart", "composingSpanEnd", "expectingUpdateSelection", "expectingUpdateSelectionFromLogger", "context" }; @@ -540,7 +540,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_PERFORMEDITORACTION = { - "LATINIME_PERFORMEDITORACTION", "imeActionNext" + "LatinIMEPerformEditorAction", "imeActionNext" }; public static void latinIME_performEditorAction(final int imeActionNext) { final Object[] values = { @@ -550,7 +550,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION = { - "LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION", "index", "text", "x", "y" + "LatinIMEPickApplicationSpecifiedCompletion", "index", "text", "x", "y" }; public static void latinIME_pickApplicationSpecifiedCompletion(final int index, final CharSequence text, int x, int y) { @@ -561,7 +561,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY = { - "LATINIME_PICKSUGGESTIONMANUALLY", "replacedWord", "index", "suggestion", "x", "y" + "LatinIMEPickSuggestionManually", "replacedWord", "index", "suggestion", "x", "y" }; public static void latinIME_pickSuggestionManually(final String replacedWord, final int index, CharSequence suggestion, int x, int y) { @@ -572,7 +572,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION = { - "LATINIME_PUNCTUATIONSUGGESTION", "index", "suggestion", "x", "y" + "LatinIMEPunctuationSuggestion", "index", "suggestion", "x", "y" }; public static void latinIME_punctuationSuggestion(final int index, final CharSequence suggestion, int x, int y) { @@ -583,7 +583,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT = { - "LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT" + "LatinIMERevertDoubleSpaceWhileInBatchEdit" }; public static void latinIME_revertDoubleSpaceWhileInBatchEdit() { getInstance().writeEvent(EVENTKEYS_LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT, @@ -591,14 +591,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_REVERTSWAPPUNCTUATION = { - "LATINIME_REVERTSWAPPUNCTUATION" + "LatinIMERevertSwapPunctuation" }; public static void latinIME_revertSwapPunctuation() { getInstance().writeEvent(EVENTKEYS_LATINIME_REVERTSWAPPUNCTUATION, EVENTKEYS_NULLVALUES); } private static final String[] EVENTKEYS_LATINIME_SENDKEYCODEPOINT = { - "LATINIME_SENDKEYCODEPOINT", "code" + "LatinIMESendKeyCodePoint", "code" }; public static void latinIME_sendKeyCodePoint(final int code) { final Object[] values = { @@ -608,7 +608,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT = { - "LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT" + "LatinIMESwapSwapperAndSpaceWhileInBatchEdit" }; public static void latinIME_swapSwapperAndSpaceWhileInBatchEdit() { getInstance().writeEvent(EVENTKEYS_LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT, @@ -616,21 +616,21 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW = { - "LATINIME_SWITCHTOKEYBOARDVIEW" + "LatinIMESwitchToKeyboardView" }; public static void latinIME_switchToKeyboardView() { getInstance().writeEvent(EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW, EVENTKEYS_NULLVALUES); } private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS = { - "LATINKEYBOARDVIEW_ONLONGPRESS" + "LatinKeyboardViewOnLongPress" }; public static void latinKeyboardView_onLongPress() { getInstance().writeEvent(EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS, EVENTKEYS_NULLVALUES); } private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD = { - "LATINKEYBOARDVIEW_SETKEYBOARD", "elementId", "locale", "orientation", "width", + "LatinKeyboardViewSetKeyboard", "elementId", "locale", "orientation", "width", "modeName", "action", "navigateNext", "navigatePrevious", "clobberSettingsKey", "passwordInput", "shortcutKeyEnabled", "hasShortcutKey", "languageSwitchKeyEnabled", "isMultiLine", "tw", "th", "keys" @@ -662,7 +662,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_LATINIME_REVERTCOMMIT = { - "LATINIME_REVERTCOMMIT", "originallyTypedWord" + "LatinIMERevertCommit", "originallyTypedWord" }; public static void latinIME_revertCommit(final String originallyTypedWord) { final Object[] values = { @@ -672,7 +672,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONCANCELINPUT = { - "POINTERTRACKER_CALLLISTENERONCANCELINPUT" + "PointerTrackerCallListenerOnCancelInput" }; public static void pointerTracker_callListenerOnCancelInput() { getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONCANCELINPUT, @@ -680,7 +680,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONCODEINPUT = { - "POINTERTRACKER_CALLLISTENERONCODEINPUT", "code", "outputText", "x", "y", + "PointerTrackerCallListenerOnCodeInput", "code", "outputText", "x", "y", "ignoreModifierKey", "altersCode", "isEnabled" }; public static void pointerTracker_callListenerOnCodeInput(final Key key, final int x, @@ -697,7 +697,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONRELEASE = { - "POINTERTRACKER_CALLLISTENERONRELEASE", "code", "withSliding", "ignoreModifierKey", + "PointerTrackerCallListenerOnRelease", "code", "withSliding", "ignoreModifierKey", "isEnabled" }; public static void pointerTracker_callListenerOnRelease(final Key key, final int primaryCode, @@ -712,7 +712,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_POINTERTRACKER_ONDOWNEVENT = { - "POINTERTRACKER_ONDOWNEVENT", "deltaT", "distanceSquared" + "PointerTrackerOnDownEvent", "deltaT", "distanceSquared" }; public static void pointerTracker_onDownEvent(long deltaT, int distanceSquared) { final Object[] values = { @@ -722,7 +722,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_POINTERTRACKER_ONMOVEEVENT = { - "POINTERTRACKER_ONMOVEEVENT", "x", "y", "lastX", "lastY" + "PointerTrackerOnMoveEvent", "x", "y", "lastX", "lastY" }; public static void pointerTracker_onMoveEvent(final int x, final int y, final int lastX, final int lastY) { @@ -733,7 +733,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT = { - "SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT", "motionEvent" + "SuddenJumpingTouchEventHandlerOnTouchEvent", "motionEvent" }; public static void suddenJumpingTouchEventHandler_onTouchEvent(final MotionEvent me) { if (me != null) { @@ -746,7 +746,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } private static final String[] EVENTKEYS_SUGGESTIONSVIEW_SETSUGGESTIONS = { - "SUGGESTIONSVIEW_SETSUGGESTIONS", "suggestedWords" + "SuggestionsViewSetSuggestions", "suggestedWords" }; public static void suggestionsView_setSuggestions(final SuggestedWords suggestedWords) { if (suggestedWords != null) { -- cgit v1.2.3-83-g751a From 724bc479f7d796d6ce5d5e200216bea855b818b2 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Mon, 4 Jun 2012 12:27:37 -0700 Subject: add research log ui control - lets users flag a particular time in the research log - lets users delete the log for this session also makes the UsabilityLog setting control whether the ResearchLog logs or not. multi-project commit with I89067e7d3b8daca7179333f1dbe82224c26920fe Bug: 6188932 Change-Id: I89864ef3ab53b0efe1ea8d75247be08712f0c399 --- java/res/values/strings.xml | 16 +++ java/res/xml/key_styles_common.xml | 19 +--- java/res/xml/key_styles_f1.xml | 43 ++++++++ .../com/android/inputmethod/keyboard/Keyboard.java | 6 +- .../keyboard/internal/KeyboardCodesSet.java | 3 + .../com/android/inputmethod/latin/LatinIME.java | 9 +- .../android/inputmethod/latin/ResearchLogger.java | 114 ++++++++++++++++++--- 7 files changed, 177 insertions(+), 33 deletions(-) create mode 100644 java/res/xml/key_styles_f1.xml (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index d51d3789a..d663b008d 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -26,6 +26,8 @@ Android keyboard settings Input options + + Research Log Commands Android spell checker @@ -233,6 +235,20 @@ Input languages + + Note timestamp in log + + Recorded timestamp + + + Do not log this session + + Deleting session log + + Session log deleted + + Session log NOT deleted + Input languages diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml index 819cdc6a9..7db1d29ea 100644 --- a/java/res/xml/key_styles_common.xml +++ b/java/res/xml/key_styles_common.xml @@ -22,23 +22,8 @@ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 0be4cf3a7..43dbecebd 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -89,7 +89,8 @@ public class Keyboard { private static final int MINIMUM_LETTER_CODE = CODE_TAB; /** Special keys code. Must be negative. - * These should be aligned with values/keycodes.xml + * These should be aligned with KeyboardCodesSet.ID_TO_NAME[], + * KeyboardCodesSet.DEFAULT[] and KeyboardCodesSet.RTL[] */ public static final int CODE_SHIFT = -1; public static final int CODE_SWITCH_ALPHA_SYMBOL = -2; @@ -101,8 +102,9 @@ public class Keyboard { public static final int CODE_ACTION_NEXT = -8; public static final int CODE_ACTION_PREVIOUS = -9; public static final int CODE_LANGUAGE_SWITCH = -10; + public static final int CODE_RESEARCH = -11; // Code value representing the code is not specified. - public static final int CODE_UNSPECIFIED = -11; + public static final int CODE_UNSPECIFIED = -12; public final KeyboardId mId; public final int mThemeId; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java index 67cb74f4d..f7981a320 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java @@ -52,6 +52,7 @@ public class KeyboardCodesSet { "key_action_next", "key_action_previous", "key_language_switch", + "key_research", "key_unspecified", "key_left_parenthesis", "key_right_parenthesis", @@ -86,6 +87,7 @@ public class KeyboardCodesSet { Keyboard.CODE_ACTION_NEXT, Keyboard.CODE_ACTION_PREVIOUS, Keyboard.CODE_LANGUAGE_SWITCH, + Keyboard.CODE_RESEARCH, Keyboard.CODE_UNSPECIFIED, CODE_LEFT_PARENTHESIS, CODE_RIGHT_PARENTHESIS, @@ -112,6 +114,7 @@ public class KeyboardCodesSet { DEFAULT[11], DEFAULT[12], DEFAULT[13], + DEFAULT[14], CODE_RIGHT_PARENTHESIS, CODE_LEFT_PARENTHESIS, CODE_GREATER_THAN_SIGN, diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 98cf76cd0..69b044e5c 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1330,6 +1330,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen case Keyboard.CODE_LANGUAGE_SWITCH: handleLanguageSwitchKey(); break; + case Keyboard.CODE_RESEARCH: + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.getInstance().presentResearchDialog(this); + } + break; default: if (primaryCode == Keyboard.CODE_TAB && mInputAttributes.mEditorAction == EditorInfo.IME_ACTION_NEXT) { @@ -2444,10 +2449,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final AlertDialog.Builder builder = new AlertDialog.Builder(this) .setItems(items, listener) .setTitle(title); - showOptionDialogInternal(builder.create()); + showOptionDialog(builder.create()); } - private void showOptionDialogInternal(AlertDialog dialog) { + /* package */ void showOptionDialog(AlertDialog dialog) { final IBinder windowToken = mKeyboardSwitcher.getKeyboardView().getWindowToken(); if (windowToken == null) return; diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 16285091b..bb003f766 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -18,6 +18,8 @@ package com.android.inputmethod.latin; import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET; +import android.app.AlertDialog; +import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.inputmethodservice.InputMethodService; @@ -33,9 +35,9 @@ import android.view.MotionEvent; 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.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardId; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; @@ -134,12 +136,16 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } if (prefs != null) { sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); - prefs.registerOnSharedPreferenceChangeListener(sInstance); + prefs.registerOnSharedPreferenceChangeListener(this); } } public synchronized void start() { Log.d(TAG, "start called"); + if (!sIsLogging) { + // Log.w(TAG, "not in usability mode; not logging"); + return; + } if (mFilesDir == null || !mFilesDir.exists()) { Log.w(TAG, "IME storage directory does not exist. Cannot start logging."); } else { @@ -192,16 +198,17 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); - } - mJsonWriter = NULL_JSON_WRITER; - mFile = null; - mLoggingState = LOGGING_STATE_OFF; - if (DEBUG) { - Log.d(TAG, "logfile closed"); - } - Log.d(TAG, "finished stop(), notifying"); - synchronized (ResearchLogger.this) { - ResearchLogger.this.notify(); + } finally { + mJsonWriter = NULL_JSON_WRITER; + mFile = null; + mLoggingState = LOGGING_STATE_OFF; + if (DEBUG) { + Log.d(TAG, "logfile closed"); + } + Log.d(TAG, "finished stop(), notifying"); + synchronized (ResearchLogger.this) { + ResearchLogger.this.notify(); + } } } }); @@ -213,6 +220,38 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } + public synchronized boolean abort() { + Log.d(TAG, "abort called"); + boolean isLogFileDeleted = false; + if (mLoggingHandler != null && mLoggingState == LOGGING_STATE_ON) { + mLoggingState = LOGGING_STATE_STOPPING; + try { + Log.d(TAG, "closing jsonwriter"); + mJsonWriter.endArray(); + mJsonWriter.close(); + } catch (IllegalStateException e1) { + // assume that this is just the json not being terminated properly. + // ignore + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + mJsonWriter = NULL_JSON_WRITER; + // delete file + final boolean isDeleted = mFile.delete(); + if (isDeleted) { + isLogFileDeleted = true; + } + mFile = null; + mLoggingState = LOGGING_STATE_OFF; + if (DEBUG) { + Log.d(TAG, "logfile closed"); + } + } + } + return isLogFileDeleted; + } + /* package */ synchronized void flush() { try { mJsonWriter.flush(); @@ -227,6 +266,50 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang return; } sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); + if (sIsLogging == false) { + abort(); + } + } + + /* package */ void presentResearchDialog(final LatinIME latinIME) { + final CharSequence title = latinIME.getString(R.string.english_ime_research_log); + final CharSequence[] items = new CharSequence[] { + latinIME.getString(R.string.note_timestamp_for_researchlog), + latinIME.getString(R.string.do_not_log_this_session), + }; + final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface di, int position) { + di.dismiss(); + switch (position) { + case 0: + ResearchLogger.getInstance().userTimestamp(); + Toast.makeText(latinIME, R.string.notify_recorded_timestamp, + Toast.LENGTH_LONG).show(); + break; + case 1: + Toast toast = Toast.makeText(latinIME, + R.string.notify_session_log_deleting, Toast.LENGTH_LONG); + toast.show(); + final ResearchLogger logger = ResearchLogger.getInstance(); + boolean isLogDeleted = logger.abort(); + toast.cancel(); + if (isLogDeleted) { + Toast.makeText(latinIME, R.string.notify_session_log_deleted, + Toast.LENGTH_LONG).show(); + } else { + Toast.makeText(latinIME, + R.string.notify_session_log_not_deleted, Toast.LENGTH_LONG) + .show(); + } + break; + } + } + }; + final AlertDialog.Builder builder = new AlertDialog.Builder(latinIME) + .setItems(items, listener) + .setTitle(title); + latinIME.showOptionDialog(builder.create()); } private static final String CURRENT_TIME_KEY = "_ct"; @@ -756,4 +839,11 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang getInstance().writeEvent(EVENTKEYS_SUGGESTIONSVIEW_SETSUGGESTIONS, values); } } + + private static final String[] EVENTKEYS_USER_TIMESTAMP = { + "UserTimestamp" + }; + public void userTimestamp() { + getInstance().writeEvent(EVENTKEYS_USER_TIMESTAMP, EVENTKEYS_NULLVALUES); + } } -- cgit v1.2.3-83-g751a From 7214617622fce8f3fea6620e782c16336260a2a3 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Fri, 8 Jun 2012 16:00:02 +0900 Subject: Remove a slew of Eclipse warnings. Change-Id: I03236386aea13fbd4fb8eaeee18e0008aa136502 --- java/src/com/android/inputmethod/keyboard/KeyboardView.java | 1 + java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java | 2 -- java/src/com/android/inputmethod/latin/ExpandableDictionary.java | 4 +++- java/src/com/android/inputmethod/latin/LatinIME.java | 1 + java/src/com/android/inputmethod/latin/ResearchLogger.java | 4 ++-- java/src/com/android/inputmethod/latin/SettingsValues.java | 1 - java/src/com/android/inputmethod/latin/UserHistoryDictionary.java | 2 +- .../android/inputmethod/latin/UserHistoryForgettingCurveUtils.java | 4 ++-- java/src/com/android/inputmethod/latin/Utils.java | 2 -- .../com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java | 2 +- 10 files changed, 11 insertions(+), 12 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 51a0f537f..18e01fb49 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -873,6 +873,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { keyPreview, ViewLayoutUtils.newLayoutParam(mPreviewPlacer, 0, 0)); } + @SuppressWarnings("deprecation") // setBackgroundDrawable is replaced by setBackground in API16 @Override public void showKeyPreview(PointerTracker tracker) { if (!mShowKeyPreviewPopup) return; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index 5aa9a0887..4ab6832c3 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -21,8 +21,6 @@ import android.util.Log; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.Constants; -import com.android.inputmethod.latin.ResearchLogger; -import com.android.inputmethod.latin.define.ProductionFlag; /** * Keyboard state machine. diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java index 34a92fd30..4a5471c85 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -514,8 +514,10 @@ public class ExpandableDictionary extends Dictionary { /** * Adds bigrams to the in-memory trie structure that is being used to retrieve any word + * @param word1 the first word of this bigram + * @param word2 the second word of this bigram * @param frequency frequency for this bigram - * @param addFrequency if true, it adds to current frequency, else it overwrites the old value + * @param fcp an instance of ForgettingCurveParams to use for decay policy * @return returns the final bigram frequency */ private int setBigramAndGetFrequency( diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index ae9e197a1..f5025e54a 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -747,6 +747,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); } + @Override public void onTargetApplicationKnown(final ApplicationInfo info) { mTargetApplicationInfo = info; } diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index bb003f766..a7e7738d8 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -101,13 +101,13 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static class NullOutputStream extends OutputStream { /** {@inheritDoc} */ @Override - public void write(byte[] buffer, int offset, int count) throws IOException { + public void write(byte[] buffer, int offset, int count) { // nop } /** {@inheritDoc} */ @Override - public void write(byte[] buffer) throws IOException { + public void write(byte[] buffer) { // nop } diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 4aae6a85e..dfe207cf2 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -29,7 +29,6 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.Map; /** * When you call the constructor of this class, you may want to change the current system locale by diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java index 9c54e0b81..10f92d29e 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java @@ -440,7 +440,7 @@ public class UserHistoryDictionary extends ExpandableDictionary { if (nw != null) { final ForgettingCurveParams fcp = nw.getFcParams(); final byte prevFc = word1Bigrams.get(word2); - final byte fc = (byte)fcp.getFc(); + final byte fc = fcp.getFc(); final boolean isValid = fcp.isValid(); if (prevFc > 0 && prevFc == fc) { // No need to update since we found no changes for this entry. diff --git a/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java b/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java index e5516dc62..3ae1bd336 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java @@ -50,7 +50,7 @@ public class UserHistoryForgettingCurveUtils { } private ForgettingCurveParams(long now, boolean isValid) { - this((int)pushCount((byte)0, isValid), now, now, isValid); + this(pushCount((byte)0, isValid), now, now, isValid); } /** This constructor is called when the user history bigram dictionary is being restored. */ @@ -201,7 +201,7 @@ public class UserHistoryForgettingCurveUtils { for (int i = 0; i < FC_LEVEL_MAX; ++i) { final double initialFreq; if (i >= 2) { - initialFreq = (double)FC_FREQ_MAX; + initialFreq = FC_FREQ_MAX; } else if (i == 1) { initialFreq = (double)FC_FREQ_MAX / 2; } else if (i == 0) { diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java index 4178955bc..903b5a357 100644 --- a/java/src/com/android/inputmethod/latin/Utils.java +++ b/java/src/com/android/inputmethod/latin/Utils.java @@ -44,10 +44,8 @@ import java.io.IOException; import java.io.PrintWriter; import java.nio.channels.FileChannel; import java.text.SimpleDateFormat; -import java.util.Collections; import java.util.Date; import java.util.HashMap; -import java.util.Map; public class Utils { private Utils() { diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 89c59f809..0c5d41a5c 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -788,7 +788,7 @@ public class BinaryDictInputOutput { // which is the best approximation. This is how we get the most precise result with // only four bits. final double stepSize = - (double)(MAX_TERMINAL_FREQUENCY - unigramFrequency) / (1.5 + MAX_BIGRAM_FREQUENCY); + (MAX_TERMINAL_FREQUENCY - unigramFrequency) / (1.5 + MAX_BIGRAM_FREQUENCY); final double firstStepStart = 1 + unigramFrequency + (stepSize / 2.0); final int discretizedFrequency = (int)((bigramFrequency - firstStepStart) / stepSize); // If the bigram freq is less than half-a-step higher than the unigram freq, we get -1 -- cgit v1.2.3-83-g751a From 02308bec632a5df23325c916bffec5def16b22b4 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Fri, 8 Jun 2012 19:44:38 +0900 Subject: Merge RichInputConnection with EditingUtils Change-Id: I9982ff325bef56694402caef28a77683c52ccd71 --- .../android/inputmethod/latin/EditingUtils.java | 218 --------------------- .../com/android/inputmethod/latin/LatinIME.java | 21 +- .../android/inputmethod/latin/ResearchLogger.java | 5 +- .../inputmethod/latin/RichInputConnection.java | 188 +++++++++++++++++- .../inputmethod/latin/EditingUtilsTests.java | 161 --------------- .../latin/RichInputConnectionTests.java | 178 +++++++++++++++++ 6 files changed, 370 insertions(+), 401 deletions(-) delete mode 100644 java/src/com/android/inputmethod/latin/EditingUtils.java delete mode 100644 tests/src/com/android/inputmethod/latin/EditingUtilsTests.java create mode 100644 tests/src/com/android/inputmethod/latin/RichInputConnectionTests.java (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/EditingUtils.java b/java/src/com/android/inputmethod/latin/EditingUtils.java deleted file mode 100644 index 479b3bf5a..000000000 --- a/java/src/com/android/inputmethod/latin/EditingUtils.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2009 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.latin; - -import android.view.inputmethod.ExtractedText; -import android.view.inputmethod.ExtractedTextRequest; -import android.view.inputmethod.InputConnection; - -import java.util.regex.Pattern; - -/** - * Utility methods to deal with editing text through an InputConnection. - */ -public class EditingUtils { - /** - * Number of characters we want to look back in order to identify the previous word - */ - // Provision for a long word pair and a separator - private static final int LOOKBACK_CHARACTER_NUM = BinaryDictionary.MAX_WORD_LENGTH * 2 + 1; - private static final int INVALID_CURSOR_POSITION = -1; - - private EditingUtils() { - // Unintentional empty constructor for singleton. - } - - private static int getCursorPosition(InputConnection connection) { - if (null == connection) return INVALID_CURSOR_POSITION; - final ExtractedText extracted = connection.getExtractedText(new ExtractedTextRequest(), 0); - if (extracted == null) { - return INVALID_CURSOR_POSITION; - } - return extracted.startOffset + extracted.selectionStart; - } - - /** - * @param connection connection to the current text field. - * @param separators characters which may separate words - * @return the word that surrounds the cursor, including up to one trailing - * separator. For example, if the field contains "he|llo world", where | - * represents the cursor, then "hello " will be returned. - */ - public static String getWordAtCursor(InputConnection connection, String separators) { - // getWordRangeAtCursor returns null if the connection is null - Range r = getWordRangeAtCursor(connection, separators, 0); - return (r == null) ? null : r.mWord; - } - - /** - * Represents a range of text, relative to the current cursor position. - */ - public static class Range { - /** Characters before selection start */ - public final int mCharsBefore; - - /** - * Characters after selection start, including one trailing word - * separator. - */ - public final int mCharsAfter; - - /** The actual characters that make up a word */ - public final String mWord; - - public Range(int charsBefore, int charsAfter, String word) { - if (charsBefore < 0 || charsAfter < 0) { - throw new IndexOutOfBoundsException(); - } - this.mCharsBefore = charsBefore; - this.mCharsAfter = charsAfter; - this.mWord = word; - } - } - - /** - * Returns the text surrounding the cursor. - * - * @param connection the InputConnection to the TextView - * @param sep a string of characters that split words. - * @param additionalPrecedingWordsCount the number of words before the current word that should - * be included in the returned range - * @return a range containing the text surrounding the cursor - */ - public static Range getWordRangeAtCursor(InputConnection connection, String sep, - int additionalPrecedingWordsCount) { - if (connection == null || sep == null) { - return null; - } - CharSequence before = connection.getTextBeforeCursor(1000, 0); - CharSequence after = connection.getTextAfterCursor(1000, 0); - if (before == null || after == null) { - return null; - } - - // Going backward, alternate skipping non-separators and separators until enough words - // have been read. - int start = before.length(); - boolean isStoppingAtWhitespace = true; // toggles to indicate what to stop at - while (true) { // see comments below for why this is guaranteed to halt - while (start > 0) { - final int codePoint = Character.codePointBefore(before, start); - if (isStoppingAtWhitespace == isSeparator(codePoint, sep)) { - break; // inner loop - } - --start; - if (Character.isSupplementaryCodePoint(codePoint)) { - --start; - } - } - // isStoppingAtWhitespace is true every other time through the loop, - // so additionalPrecedingWordsCount is guaranteed to become < 0, which - // guarantees outer loop termination - if (isStoppingAtWhitespace && (--additionalPrecedingWordsCount < 0)) { - break; // outer loop - } - isStoppingAtWhitespace = !isStoppingAtWhitespace; - } - - // Find last word separator after the cursor - int end = -1; - while (++end < after.length()) { - final int codePoint = Character.codePointAt(after, end); - if (isSeparator(codePoint, sep)) { - break; - } - if (Character.isSupplementaryCodePoint(codePoint)) { - ++end; - } - } - - int cursor = getCursorPosition(connection); - if (start >= 0 && cursor + end <= after.length() + before.length()) { - String word = before.toString().substring(start, before.length()) - + after.toString().substring(0, end); - return new Range(before.length() - start, end, word); - } - - return null; - } - - private static boolean isSeparator(int code, String sep) { - return sep.indexOf(code) != -1; - } - - private static final Pattern spaceRegex = Pattern.compile("\\s+"); - - public static CharSequence getPreviousWord(InputConnection connection, - String sentenceSeperators) { - //TODO: Should fix this. This could be slow! - if (null == connection) return null; - CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); - return getPreviousWord(prev, sentenceSeperators); - } - - // Get the word before the whitespace preceding the non-whitespace preceding the cursor. - // Also, it won't return words that end in a separator. - // Example : - // "abc def|" -> abc - // "abc def |" -> abc - // "abc def. |" -> abc - // "abc def . |" -> def - // "abc|" -> null - // "abc |" -> null - // "abc. def|" -> null - public static CharSequence getPreviousWord(CharSequence prev, String sentenceSeperators) { - if (prev == null) return null; - String[] w = spaceRegex.split(prev); - - // If we can't find two words, or we found an empty word, return null. - if (w.length < 2 || w[w.length - 2].length() <= 0) return null; - - // If ends in a separator, return null - char lastChar = w[w.length - 2].charAt(w[w.length - 2].length() - 1); - if (sentenceSeperators.contains(String.valueOf(lastChar))) return null; - - return w[w.length - 2]; - } - - public static CharSequence getThisWord(InputConnection connection, String sentenceSeperators) { - if (null == connection) return null; - final CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); - return getThisWord(prev, sentenceSeperators); - } - - // Get the word immediately before the cursor, even if there is whitespace between it and - // the cursor - but not if there is punctuation. - // Example : - // "abc def|" -> def - // "abc def |" -> def - // "abc def. |" -> null - // "abc def . |" -> null - public static CharSequence getThisWord(CharSequence prev, String sentenceSeperators) { - if (prev == null) return null; - String[] w = spaceRegex.split(prev); - - // No word : return null - if (w.length < 1 || w[w.length - 1].length() <= 0) return null; - - // If ends in a separator, return null - char lastChar = w[w.length - 1].charAt(w[w.length - 1].length() - 1); - if (sentenceSeperators.contains(String.valueOf(lastChar))) return null; - - return w[w.length - 1]; - } -} diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 5b499e4be..656f6d7b3 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -783,7 +783,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen ResearchLogger.latinIME_onUpdateSelection(mLastSelectionStart, mLastSelectionEnd, oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, composingSpanEnd, mExpectingUpdateSelection, - expectingUpdateSelectionFromLogger, getCurrentInputConnection()); + expectingUpdateSelectionFromLogger, mConnection); if (expectingUpdateSelectionFromLogger) { return; } @@ -1760,11 +1760,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } // TODO: May need a better way of retrieving previous word - final CharSequence prevWord; - // TODO: move getPreviousWord to AutoInputConnection - prevWord = EditingUtils.getPreviousWord(mConnection.getInputConnection(), - mSettingsValues.mWordSeparators); - + final CharSequence prevWord = mConnection.getPreviousWord(mSettingsValues.mWordSeparators); final CharSequence typedWord = mWordComposer.getTypedWord(); // getSuggestedWords handles gracefully a null value of prevWord final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer, @@ -1993,8 +1989,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final SuggestedWords suggestedWords; if (mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { - final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(), - mSettingsValues.mWordSeparators); + final CharSequence prevWord = mConnection.getThisWord(mSettingsValues.mWordSeparators); if (!TextUtils.isEmpty(prevWord)) { suggestedWords = mSuggest.getBigramPredictions(prevWord); } else { @@ -2031,10 +2026,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } if (mUserHistoryDictionary != null) { - final CharSequence prevWord; - // TODO: move getPreviousWord to AutoInputConnection - prevWord = EditingUtils.getPreviousWord(mConnection.getInputConnection(), - mSettingsValues.mWordSeparators); + final CharSequence prevWord + = mConnection.getPreviousWord(mSettingsValues.mWordSeparators); final String secondWord; if (mWordComposer.isAutoCapitalized() && !mWordComposer.isMostlyCaps()) { secondWord = suggestion.toString().toLowerCase( @@ -2093,9 +2086,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Bail out if word before cursor is 0-length or a single non letter (like an apostrophe) // Example: " -|" gets rejected here but "e-|" and "e|" are okay - // TODO: move getWordAtCursor inside AutoInputConnection - CharSequence word = EditingUtils.getWordAtCursor(mConnection.getInputConnection(), - mSettingsValues.mWordSeparators); + CharSequence word = mConnection.getWordAtCursor(mSettingsValues.mWordSeparators); // We don't suggest on leading single quotes, so we have to remove them from the word if // it starts with single quotes. while (!TextUtils.isEmpty(word) && Keyboard.CODE_SINGLE_QUOTE == word.charAt(0)) { diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index a7e7738d8..f27d07074 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -612,12 +612,13 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang 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 InputConnection connection) { + final boolean expectingUpdateSelectionFromLogger, + final RichInputConnection connection) { final Object[] values = { lastSelectionStart, lastSelectionEnd, oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, composingSpanEnd, expectingUpdateSelection, expectingUpdateSelectionFromLogger, - EditingUtils.getWordRangeAtCursor(connection, WHITESPACE_SEPARATORS, 1).mWord + connection.getWordRangeAtCursor(WHITESPACE_SEPARATORS, 1).mWord }; getInstance().writeEvent(EVENTKEYS_LATINIME_ONUPDATESELECTION, values); } diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index 449d08e9b..c9ee09396 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -20,14 +20,23 @@ import android.util.Log; import android.view.KeyEvent; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CorrectionInfo; +import android.view.inputmethod.ExtractedText; +import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; +import java.util.regex.Pattern; + /** * Wrapper for InputConnection to simplify interaction */ public class RichInputConnection { private static final String TAG = RichInputConnection.class.getSimpleName(); private static final boolean DBG = false; + // Provision for a long word pair and a separator + private static final int LOOKBACK_CHARACTER_NUM = BinaryDictionary.MAX_WORD_LENGTH * 2 + 1; + private static final Pattern spaceRegex = Pattern.compile("\\s+"); + private static final int INVALID_CURSOR_POSITION = -1; + InputConnection mIC; int mNestLevel; public RichInputConnection() { @@ -35,11 +44,6 @@ public class RichInputConnection { mNestLevel = 0; } - // TODO: remove this method - the whole point of this class is void if mIC is escaping - public InputConnection getInputConnection() { - return mIC; - } - public void beginBatchEdit(final InputConnection newInputConnection) { if (++mNestLevel == 1) { mIC = newInputConnection; @@ -119,4 +123,178 @@ public class RichInputConnection { if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead if (null != mIC) mIC.commitCompletion(completionInfo); } + + public CharSequence getPreviousWord(final String sentenceSeperators) { + //TODO: Should fix this. This could be slow! + if (null == mIC) return null; + CharSequence prev = mIC.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); + return getPreviousWord(prev, sentenceSeperators); + } + + /** + * Represents a range of text, relative to the current cursor position. + */ + public static class Range { + /** Characters before selection start */ + public final int mCharsBefore; + + /** + * Characters after selection start, including one trailing word + * separator. + */ + public final int mCharsAfter; + + /** The actual characters that make up a word */ + public final String mWord; + + public Range(int charsBefore, int charsAfter, String word) { + if (charsBefore < 0 || charsAfter < 0) { + throw new IndexOutOfBoundsException(); + } + this.mCharsBefore = charsBefore; + this.mCharsAfter = charsAfter; + this.mWord = word; + } + } + + private static boolean isSeparator(int code, String sep) { + return sep.indexOf(code) != -1; + } + + // Get the word before the whitespace preceding the non-whitespace preceding the cursor. + // Also, it won't return words that end in a separator. + // Example : + // "abc def|" -> abc + // "abc def |" -> abc + // "abc def. |" -> abc + // "abc def . |" -> def + // "abc|" -> null + // "abc |" -> null + // "abc. def|" -> null + public static CharSequence getPreviousWord(CharSequence prev, String sentenceSeperators) { + if (prev == null) return null; + String[] w = spaceRegex.split(prev); + + // If we can't find two words, or we found an empty word, return null. + if (w.length < 2 || w[w.length - 2].length() <= 0) return null; + + // If ends in a separator, return null + char lastChar = w[w.length - 2].charAt(w[w.length - 2].length() - 1); + if (sentenceSeperators.contains(String.valueOf(lastChar))) return null; + + return w[w.length - 2]; + } + + public CharSequence getThisWord(String sentenceSeperators) { + if (null == mIC) return null; + final CharSequence prev = mIC.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); + return getThisWord(prev, sentenceSeperators); + } + + // Get the word immediately before the cursor, even if there is whitespace between it and + // the cursor - but not if there is punctuation. + // Example : + // "abc def|" -> def + // "abc def |" -> def + // "abc def. |" -> null + // "abc def . |" -> null + public static CharSequence getThisWord(CharSequence prev, String sentenceSeperators) { + if (prev == null) return null; + String[] w = spaceRegex.split(prev); + + // No word : return null + if (w.length < 1 || w[w.length - 1].length() <= 0) return null; + + // If ends in a separator, return null + char lastChar = w[w.length - 1].charAt(w[w.length - 1].length() - 1); + if (sentenceSeperators.contains(String.valueOf(lastChar))) return null; + + return w[w.length - 1]; + } + + /** + * @param separators characters which may separate words + * @return the word that surrounds the cursor, including up to one trailing + * separator. For example, if the field contains "he|llo world", where | + * represents the cursor, then "hello " will be returned. + */ + public String getWordAtCursor(String separators) { + // getWordRangeAtCursor returns null if the connection is null + Range r = getWordRangeAtCursor(separators, 0); + return (r == null) ? null : r.mWord; + } + + private int getCursorPosition() { + if (null == mIC) return INVALID_CURSOR_POSITION; + final ExtractedText extracted = mIC.getExtractedText(new ExtractedTextRequest(), 0); + if (extracted == null) { + return INVALID_CURSOR_POSITION; + } + return extracted.startOffset + extracted.selectionStart; + } + + /** + * Returns the text surrounding the cursor. + * + * @param sep a string of characters that split words. + * @param additionalPrecedingWordsCount the number of words before the current word that should + * be included in the returned range + * @return a range containing the text surrounding the cursor + */ + public Range getWordRangeAtCursor(String sep, int additionalPrecedingWordsCount) { + if (mIC == null || sep == null) { + return null; + } + CharSequence before = mIC.getTextBeforeCursor(1000, 0); + CharSequence after = mIC.getTextAfterCursor(1000, 0); + if (before == null || after == null) { + return null; + } + + // Going backward, alternate skipping non-separators and separators until enough words + // have been read. + int start = before.length(); + boolean isStoppingAtWhitespace = true; // toggles to indicate what to stop at + while (true) { // see comments below for why this is guaranteed to halt + while (start > 0) { + final int codePoint = Character.codePointBefore(before, start); + if (isStoppingAtWhitespace == isSeparator(codePoint, sep)) { + break; // inner loop + } + --start; + if (Character.isSupplementaryCodePoint(codePoint)) { + --start; + } + } + // isStoppingAtWhitespace is true every other time through the loop, + // so additionalPrecedingWordsCount is guaranteed to become < 0, which + // guarantees outer loop termination + if (isStoppingAtWhitespace && (--additionalPrecedingWordsCount < 0)) { + break; // outer loop + } + isStoppingAtWhitespace = !isStoppingAtWhitespace; + } + + // Find last word separator after the cursor + int end = -1; + while (++end < after.length()) { + final int codePoint = Character.codePointAt(after, end); + if (isSeparator(codePoint, sep)) { + break; + } + if (Character.isSupplementaryCodePoint(codePoint)) { + ++end; + } + } + + int cursor = getCursorPosition(); + if (start >= 0 && cursor + end <= after.length() + before.length()) { + String word = before.toString().substring(start, before.length()) + + after.toString().substring(0, end); + return new Range(before.length() - start, end, word); + } + + return null; + } + } diff --git a/tests/src/com/android/inputmethod/latin/EditingUtilsTests.java b/tests/src/com/android/inputmethod/latin/EditingUtilsTests.java deleted file mode 100644 index c73f8891f..000000000 --- a/tests/src/com/android/inputmethod/latin/EditingUtilsTests.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2010 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.latin; - -import android.test.AndroidTestCase; -import android.view.inputmethod.ExtractedText; -import android.view.inputmethod.ExtractedTextRequest; -import android.view.inputmethod.InputConnection; -import android.view.inputmethod.InputConnectionWrapper; - -import com.android.inputmethod.latin.EditingUtils.Range; - -public class EditingUtilsTests extends AndroidTestCase { - - // The following is meant to be a reasonable default for - // the "word_separators" resource. - private static final String sSeparators = ".,:;!?-"; - - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - private class MockConnection extends InputConnectionWrapper { - final String mTextBefore; - final String mTextAfter; - final ExtractedText mExtractedText; - - public MockConnection(String textBefore, String textAfter, ExtractedText extractedText) { - super(null, false); - mTextBefore = textBefore; - mTextAfter = textAfter; - mExtractedText = extractedText; - } - - /* (non-Javadoc) - * @see android.view.inputmethod.InputConnectionWrapper#getTextBeforeCursor(int, int) - */ - @Override - public CharSequence getTextBeforeCursor(int n, int flags) { - return mTextBefore; - } - - /* (non-Javadoc) - * @see android.view.inputmethod.InputConnectionWrapper#getTextAfterCursor(int, int) - */ - @Override - public CharSequence getTextAfterCursor(int n, int flags) { - return mTextAfter; - } - - /* (non-Javadoc) - * @see android.view.inputmethod.InputConnectionWrapper#getExtractedText(ExtractedTextRequest, int) - */ - @Override - public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) { - return mExtractedText; - } - } - - /************************** Tests ************************/ - - /** - * Test for getting previous word (for bigram suggestions) - */ - public void testGetPreviousWord() { - // If one of the following cases breaks, the bigram suggestions won't work. - assertEquals(EditingUtils.getPreviousWord("abc def", sSeparators), "abc"); - assertNull(EditingUtils.getPreviousWord("abc", sSeparators)); - assertNull(EditingUtils.getPreviousWord("abc. def", sSeparators)); - - // The following tests reflect the current behavior of the function - // EditingUtils#getPreviousWord. - // TODO: However at this time, the code does never go - // into such a path, so it should be safe to change the behavior of - // this function if needed - especially since it does not seem very - // logical. These tests are just there to catch any unintentional - // changes in the behavior of the EditingUtils#getPreviousWord method. - assertEquals(EditingUtils.getPreviousWord("abc def ", sSeparators), "abc"); - assertEquals(EditingUtils.getPreviousWord("abc def.", sSeparators), "abc"); - assertEquals(EditingUtils.getPreviousWord("abc def .", sSeparators), "def"); - assertNull(EditingUtils.getPreviousWord("abc ", sSeparators)); - } - - /** - * Test for getting the word before the cursor (for bigram) - */ - public void testGetThisWord() { - assertEquals(EditingUtils.getThisWord("abc def", sSeparators), "def"); - assertEquals(EditingUtils.getThisWord("abc def ", sSeparators), "def"); - assertNull(EditingUtils.getThisWord("abc def.", sSeparators)); - assertNull(EditingUtils.getThisWord("abc def .", sSeparators)); - } - - /** - * Test logic in getting the word range at the cursor. - */ - public void testGetWordRangeAtCursor() { - ExtractedText et = new ExtractedText(); - InputConnection mockConnection; - mockConnection = new MockConnection("word wo", "rd", et); - et.startOffset = 0; - et.selectionStart = 7; - Range r; - - // basic case - r = EditingUtils.getWordRangeAtCursor(mockConnection, " ", 0); - assertEquals("word", r.mWord); - r = null; - - // more than one word - r = EditingUtils.getWordRangeAtCursor(mockConnection, " ", 1); - assertEquals("word word", r.mWord); - r = null; - - // tab character instead of space - mockConnection = new MockConnection("one\tword\two", "rd", et); - r = EditingUtils.getWordRangeAtCursor(mockConnection, "\t", 1); - assertEquals("word\tword", r.mWord); - r = null; - - // only one word doesn't go too far - mockConnection = new MockConnection("one\tword\two", "rd", et); - r = EditingUtils.getWordRangeAtCursor(mockConnection, "\t", 1); - assertEquals("word\tword", r.mWord); - r = null; - - // tab or space - mockConnection = new MockConnection("one word\two", "rd", et); - r = EditingUtils.getWordRangeAtCursor(mockConnection, " \t", 1); - assertEquals("word\tword", r.mWord); - r = null; - - // tab or space multiword - mockConnection = new MockConnection("one word\two", "rd", et); - r = EditingUtils.getWordRangeAtCursor(mockConnection, " \t", 2); - assertEquals("one word\tword", r.mWord); - r = null; - - // splitting on supplementary character - final String supplementaryChar = "\uD840\uDC8A"; - mockConnection = new MockConnection("one word" + supplementaryChar + "wo", "rd", et); - r = EditingUtils.getWordRangeAtCursor(mockConnection, supplementaryChar, 0); - assertEquals("word", r.mWord); - r = null; - } -} diff --git a/tests/src/com/android/inputmethod/latin/RichInputConnectionTests.java b/tests/src/com/android/inputmethod/latin/RichInputConnectionTests.java new file mode 100644 index 000000000..9ce581df8 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/RichInputConnectionTests.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2010 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.latin; + +import android.test.AndroidTestCase; +import android.view.inputmethod.ExtractedText; +import android.view.inputmethod.ExtractedTextRequest; +import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputConnectionWrapper; + +import com.android.inputmethod.latin.RichInputConnection.Range; + +public class RichInputConnectionTests extends AndroidTestCase { + + // The following is meant to be a reasonable default for + // the "word_separators" resource. + private static final String sSeparators = ".,:;!?-"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + private class MockConnection extends InputConnectionWrapper { + final String mTextBefore; + final String mTextAfter; + final ExtractedText mExtractedText; + + public MockConnection(String textBefore, String textAfter, ExtractedText extractedText) { + super(null, false); + mTextBefore = textBefore; + mTextAfter = textAfter; + mExtractedText = extractedText; + } + + /* (non-Javadoc) + * @see android.view.inputmethod.InputConnectionWrapper#getTextBeforeCursor(int, int) + */ + @Override + public CharSequence getTextBeforeCursor(int n, int flags) { + return mTextBefore; + } + + /* (non-Javadoc) + * @see android.view.inputmethod.InputConnectionWrapper#getTextAfterCursor(int, int) + */ + @Override + public CharSequence getTextAfterCursor(int n, int flags) { + return mTextAfter; + } + + /* (non-Javadoc) + * @see android.view.inputmethod.InputConnectionWrapper#getExtractedText( + * ExtractedTextRequest, int) + */ + @Override + public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) { + return mExtractedText; + } + + @Override + public boolean beginBatchEdit() { + return true; + } + + @Override + public boolean endBatchEdit() { + return true; + } + } + + /************************** Tests ************************/ + + /** + * Test for getting previous word (for bigram suggestions) + */ + public void testGetPreviousWord() { + // If one of the following cases breaks, the bigram suggestions won't work. + assertEquals(RichInputConnection.getPreviousWord("abc def", sSeparators), "abc"); + assertNull(RichInputConnection.getPreviousWord("abc", sSeparators)); + assertNull(RichInputConnection.getPreviousWord("abc. def", sSeparators)); + + // The following tests reflect the current behavior of the function + // RichInputConnection#getPreviousWord. + // TODO: However at this time, the code does never go + // into such a path, so it should be safe to change the behavior of + // this function if needed - especially since it does not seem very + // logical. These tests are just there to catch any unintentional + // changes in the behavior of the RichInputConnection#getPreviousWord method. + assertEquals(RichInputConnection.getPreviousWord("abc def ", sSeparators), "abc"); + assertEquals(RichInputConnection.getPreviousWord("abc def.", sSeparators), "abc"); + assertEquals(RichInputConnection.getPreviousWord("abc def .", sSeparators), "def"); + assertNull(RichInputConnection.getPreviousWord("abc ", sSeparators)); + } + + /** + * Test for getting the word before the cursor (for bigram) + */ + public void testGetThisWord() { + assertEquals(RichInputConnection.getThisWord("abc def", sSeparators), "def"); + assertEquals(RichInputConnection.getThisWord("abc def ", sSeparators), "def"); + assertNull(RichInputConnection.getThisWord("abc def.", sSeparators)); + assertNull(RichInputConnection.getThisWord("abc def .", sSeparators)); + } + + /** + * Test logic in getting the word range at the cursor. + */ + public void testGetWordRangeAtCursor() { + ExtractedText et = new ExtractedText(); + final RichInputConnection ic = new RichInputConnection(); + InputConnection mockConnection; + mockConnection = new MockConnection("word wo", "rd", et); + et.startOffset = 0; + et.selectionStart = 7; + Range r; + + ic.beginBatchEdit(mockConnection); + // basic case + r = ic.getWordRangeAtCursor(" ", 0); + assertEquals("word", r.mWord); + + // more than one word + r = ic.getWordRangeAtCursor(" ", 1); + assertEquals("word word", r.mWord); + ic.endBatchEdit(); + + // tab character instead of space + mockConnection = new MockConnection("one\tword\two", "rd", et); + ic.beginBatchEdit(mockConnection); + r = ic.getWordRangeAtCursor("\t", 1); + ic.endBatchEdit(); + assertEquals("word\tword", r.mWord); + + // only one word doesn't go too far + mockConnection = new MockConnection("one\tword\two", "rd", et); + ic.beginBatchEdit(mockConnection); + r = ic.getWordRangeAtCursor("\t", 1); + ic.endBatchEdit(); + assertEquals("word\tword", r.mWord); + + // tab or space + mockConnection = new MockConnection("one word\two", "rd", et); + ic.beginBatchEdit(mockConnection); + r = ic.getWordRangeAtCursor(" \t", 1); + ic.endBatchEdit(); + assertEquals("word\tword", r.mWord); + + // tab or space multiword + mockConnection = new MockConnection("one word\two", "rd", et); + ic.beginBatchEdit(mockConnection); + r = ic.getWordRangeAtCursor(" \t", 2); + ic.endBatchEdit(); + assertEquals("one word\tword", r.mWord); + + // splitting on supplementary character + final String supplementaryChar = "\uD840\uDC8A"; + mockConnection = new MockConnection("one word" + supplementaryChar + "wo", "rd", et); + ic.beginBatchEdit(mockConnection); + r = ic.getWordRangeAtCursor(supplementaryChar, 0); + ic.endBatchEdit(); + assertEquals("word", r.mWord); + } +} -- cgit v1.2.3-83-g751a From 65fc909e13134d34e87d5d75ff4cdd46fb9cebf0 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Tue, 12 Jun 2012 10:56:03 -0700 Subject: Check inputs to ResearchLogger to avoid NPEs. Bug: 6188932 Change-Id: I377ceaac867df879dc7984dae44e96b369858cca --- .../android/inputmethod/latin/ResearchLogger.java | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index f27d07074..46efa78f1 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -40,6 +40,7 @@ import android.widget.Toast; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardId; +import com.android.inputmethod.latin.RichInputConnection.Range; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.define.ProductionFlag; @@ -614,11 +615,17 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang 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; + } + } final Object[] values = { lastSelectionStart, lastSelectionEnd, oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, composingSpanEnd, expectingUpdateSelection, - expectingUpdateSelectionFromLogger, - connection.getWordRangeAtCursor(WHITESPACE_SEPARATORS, 1).mWord + expectingUpdateSelectionFromLogger, word }; getInstance().writeEvent(EVENTKEYS_LATINIME_ONUPDATESELECTION, values); } @@ -637,9 +644,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang "LatinIMEPickApplicationSpecifiedCompletion", "index", "text", "x", "y" }; public static void latinIME_pickApplicationSpecifiedCompletion(final int index, - final CharSequence text, int x, int y) { + final CharSequence cs, int x, int y) { final Object[] values = { - index, text.toString(), x, y + index, cs, x, y }; getInstance().writeEvent(EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION, values); } @@ -650,7 +657,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang public static void latinIME_pickSuggestionManually(final String replacedWord, final int index, CharSequence suggestion, int x, int y) { final Object[] values = { - replacedWord, index, suggestion.toString(), x, y + replacedWord, index, suggestion, x, y }; getInstance().writeEvent(EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY, values); } @@ -661,7 +668,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang public static void latinIME_punctuationSuggestion(final int index, final CharSequence suggestion, int x, int y) { final Object[] values = { - index, suggestion.toString(), x, y + index, suggestion, x, y }; getInstance().writeEvent(EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION, values); } @@ -773,8 +780,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang if (key != null) { CharSequence outputText = key.mOutputText; final Object[] values = { - Keyboard.printableCode(code), outputText == null ? "" : outputText.toString(), - x, y, ignoreModifierKey, altersCode, key.isEnabled() + Keyboard.printableCode(code), outputText, x, y, ignoreModifierKey, altersCode, + key.isEnabled() }; getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONCODEINPUT, values); } -- cgit v1.2.3-83-g751a From 1cef91e4818790ea5419a6ad9ff6e36ac535c763 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Wed, 13 Jun 2012 16:37:20 -0700 Subject: No logging of passwords. Bug: 6188932 Change-Id: Ibf60ec99c50da3675bf89858624218e6cc3eb1d2 --- .../src/com/android/inputmethod/latin/ResearchLogger.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 46efa78f1..5779d99bd 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -94,6 +94,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final int LOGGING_STATE_OFF = 0; private static final int LOGGING_STATE_ON = 1; private static final int LOGGING_STATE_STOPPING = 2; + private boolean mIsPasswordView = false; // set when LatinIME should ignore an onUpdateSelection() callback that // arises from operations in this class @@ -313,6 +314,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang latinIME.showOptionDialog(builder.create()); } + private void setIsPasswordView(boolean isPasswordView) { + mIsPasswordView = isPasswordView; + } + + private boolean isAllowedToLog() { + return mLoggingState == LOGGING_STATE_ON && !mIsPasswordView; + } + private static final String CURRENT_TIME_KEY = "_ct"; private static final String UPTIME_KEY = "_ut"; private static final String EVENT_TYPE_KEY = "_ty"; @@ -329,7 +338,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang */ private synchronized void writeEvent(final String[] keys, final Object[] values) { assert values.length + 1 == keys.length; - if (mLoggingState == LOGGING_STATE_ON) { + if (isAllowedToLog()) { mLoggingHandler.post(new Runnable() { @Override public void run() { @@ -729,6 +738,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang public static void latinKeyboardView_setKeyboard(final Keyboard keyboard) { if (keyboard != null) { final KeyboardId kid = keyboard.mId; + boolean isPasswordView = kid.passwordInput(); final Object[] values = { KeyboardId.elementIdToName(kid.mElementId), kid.mLocale + ":" + kid.mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET), @@ -739,7 +749,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang kid.navigateNext(), kid.navigatePrevious(), kid.mClobberSettingsKey, - kid.passwordInput(), + isPasswordView, kid.mShortcutKeyEnabled, kid.mHasShortcutKey, kid.mLanguageSwitchKeyEnabled, @@ -749,6 +759,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang keyboard.mKeys }; getInstance().writeEvent(EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD, values); + getInstance().setIsPasswordView(isPasswordView); } } -- cgit v1.2.3-83-g751a From a696781c2b18d8002275aa89e07fa7379661d025 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Thu, 14 Jun 2012 22:15:27 -0700 Subject: Replace digits in ResearchLogger Digits may represent personally identifying information. They are now replaced with a non-identifying symbol. multi-project commit with I07d1cfdc45f6086f67af45775f4ed12da1833aca Bug: 6188932 Change-Id: Ifda8079e6c1f29b5f8af34c6d1fccf5770f164ca --- .../android/inputmethod/latin/ResearchLogger.java | 65 ++++++++++++++++------ 1 file changed, 49 insertions(+), 16 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 5779d99bd..7f541cfae 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -96,6 +96,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final int LOGGING_STATE_STOPPING = 2; private boolean mIsPasswordView = false; + // 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" // set when LatinIME should ignore an onUpdateSelection() callback that // arises from operations in this class private static boolean sLatinIMEExpectingUpdateSelection = false; @@ -361,7 +364,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang CompletionInfo[] ci = (CompletionInfo[]) value; mJsonWriter.beginArray(); for (int j = 0; j < ci.length; j++) { - mJsonWriter.value(ci[j].toString()); + mJsonWriter.value(scrubDigitsFromString(ci[j].toString())); } mJsonWriter.endArray(); } else if (value instanceof SharedPreferences) { @@ -414,7 +417,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final int size = words.size(); for (int j = 0; j < size; j++) { SuggestedWordInfo wordInfo = words.getWordInfo(j); - mJsonWriter.value(wordInfo.toString()); + mJsonWriter.value(scrubDigitsFromString(wordInfo.toString())); } mJsonWriter.endArray(); mJsonWriter.endObject(); @@ -446,6 +449,34 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } + 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)) { + 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 static final String[] EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT = { "LatinKeyboardViewProcessMotionEvent", "action", "eventTime", "id", "x", "y", "size", "pressure" @@ -478,7 +509,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang }; public static void latinIME_onCodeInput(final int code, final int x, final int y) { final Object[] values = { - Keyboard.printableCode(code), x, y + Keyboard.printableCode(scrubDigitFromCodePoint(code)), x, y }; getInstance().writeEvent(EVENTKEYS_LATINIME_ONCODEINPUT, values); } @@ -489,7 +520,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang public static void logCorrection(final String subgroup, final String before, final String after, final int position) { final Object[] values = { - subgroup, before, after, position + subgroup, scrubDigitsFromString(before), scrubDigitsFromString(after), position }; getInstance().writeEvent(EVENTKEYS_CORRECTION, values); } @@ -500,7 +531,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang public static void latinIME_commitCurrentAutoCorrection(final String typedWord, final String autoCorrection) { final Object[] values = { - typedWord, autoCorrection + scrubDigitsFromString(typedWord), scrubDigitsFromString(autoCorrection) }; getInstance().writeEvent(EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION, values); } @@ -510,7 +541,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang }; public static void latinIME_commitText(final CharSequence typedWord) { final Object[] values = { - typedWord.toString() + scrubDigitsFromString(typedWord.toString()) }; getInstance().writeEvent(EVENTKEYS_LATINIME_COMMITTEXT, values); } @@ -575,10 +606,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } final CharSequence truncatedCharSequence = charSequence.subSequence(0, length); values[0] = true; - values[1] = truncatedCharSequence.toString(); + values[1] = scrubDigitsFromString(truncatedCharSequence.toString()); } else { values[0] = false; - values[1] = charSequence.toString(); + values[1] = scrubDigitsFromString(charSequence.toString()); } } getInstance().writeEvent(EVENTKEYS_LATINIME_ONWINDOWHIDDEN, values); @@ -634,7 +665,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { lastSelectionStart, lastSelectionEnd, oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, composingSpanEnd, expectingUpdateSelection, - expectingUpdateSelectionFromLogger, word + expectingUpdateSelectionFromLogger, scrubDigitsFromString(word) }; getInstance().writeEvent(EVENTKEYS_LATINIME_ONUPDATESELECTION, values); } @@ -666,7 +697,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang public static void latinIME_pickSuggestionManually(final String replacedWord, final int index, CharSequence suggestion, int x, int y) { final Object[] values = { - replacedWord, index, suggestion, x, y + scrubDigitsFromString(replacedWord), index, suggestion == null ? null : + scrubDigitsFromString(suggestion.toString()), x, y }; getInstance().writeEvent(EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY, values); } @@ -702,7 +734,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang }; public static void latinIME_sendKeyCodePoint(final int code) { final Object[] values = { - code + Keyboard.printableCode(scrubDigitFromCodePoint(code)) }; getInstance().writeEvent(EVENTKEYS_LATINIME_SENDKEYCODEPOINT, values); } @@ -738,7 +770,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang public static void latinKeyboardView_setKeyboard(final Keyboard keyboard) { if (keyboard != null) { final KeyboardId kid = keyboard.mId; - boolean isPasswordView = kid.passwordInput(); + final boolean isPasswordView = kid.passwordInput(); final Object[] values = { KeyboardId.elementIdToName(kid.mElementId), kid.mLocale + ":" + kid.mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET), @@ -791,8 +823,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang if (key != null) { CharSequence outputText = key.mOutputText; final Object[] values = { - Keyboard.printableCode(code), outputText, x, y, ignoreModifierKey, altersCode, - key.isEnabled() + Keyboard.printableCode(scrubDigitFromCodePoint(code)), outputText == null ? null + : scrubDigitsFromString(outputText.toString()), + x, y, ignoreModifierKey, altersCode, key.isEnabled() }; getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONCODEINPUT, values); } @@ -806,8 +839,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final boolean withSliding, final boolean ignoreModifierKey) { if (key != null) { final Object[] values = { - Keyboard.printableCode(primaryCode), withSliding, ignoreModifierKey, - key.isEnabled() + Keyboard.printableCode(scrubDigitFromCodePoint(primaryCode)), withSliding, + ignoreModifierKey, key.isEnabled() }; getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONRELEASE, values); } -- cgit v1.2.3-83-g751a From 6080f6878b10916013a8a5e1d5f58f8041452c56 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Fri, 15 Jun 2012 17:49:42 -0700 Subject: Remove non-dictionary words and digit touch data. Output to the ResearchLogger is now queued and only flushed if the word the user was working on is a dictionary word. multi-project commit with Ic713ec00777fbdcf4a937b3c77b995257e100fc7 Bug: 6188932 Change-Id: I9de15227ff51be23083d9096f1c1b3d83802fff7 --- .../com/android/inputmethod/latin/Dictionary.java | 8 + .../inputmethod/latin/DictionaryCollection.java | 5 +- .../com/android/inputmethod/latin/LatinIME.java | 3 + .../android/inputmethod/latin/ResearchLogger.java | 433 +++++++++++++-------- .../src/com/android/inputmethod/latin/Suggest.java | 18 +- 5 files changed, 305 insertions(+), 162 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java index 7cd9bc2a8..9c3d46e70 100644 --- a/java/src/com/android/inputmethod/latin/Dictionary.java +++ b/java/src/com/android/inputmethod/latin/Dictionary.java @@ -115,4 +115,12 @@ public abstract class Dictionary { public void close() { // empty base implementation } + + /** + * Subclasses may override to indicate that this Dictionary is not yet properly initialized. + */ + + public boolean isInitialized() { + return true; + } } diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java index 1a05fcd86..26c2e637e 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java +++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java @@ -82,8 +82,9 @@ public class DictionaryCollection extends Dictionary { return maxFreq; } - public boolean isEmpty() { - return mDictionaries.isEmpty(); + @Override + public boolean isInitialized() { + return !mDictionaries.isEmpty(); } @Override diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 107d9344e..559f5ec26 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -456,6 +456,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } mIsMainDictionaryAvailable = DictionaryFactory.isDictionaryAvailable(this, subtypeLocale); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.getInstance().initSuggest(mSuggest); + } mUserDictionary = new UserBinaryDictionary(this, localeStr); mIsUserDictionaryAvailable = mUserDictionary.isEnabled(); diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 7f541cfae..ee596924f 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -51,7 +51,9 @@ import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.UUID; @@ -67,6 +69,7 @@ import java.util.UUID; public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = ResearchLogger.class.getSimpleName(); private static final boolean DEBUG = false; + private static final boolean OUTPUT_ENTIRE_BUFFER = false; // true may disclose private info /* package */ static boolean sIsLogging = false; private static final int OUTPUT_FORMAT_VERSION = 1; private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; @@ -99,10 +102,16 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang // 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"; // 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 Dictionary mDictionary; + private static class NullOutputStream extends OutputStream { /** {@inheritDoc} */ @Override @@ -317,6 +326,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang latinIME.showOptionDialog(builder.create()); } + public void initSuggest(Suggest suggest) { + mSuggest = suggest; + } + private void setIsPasswordView(boolean isPasswordView) { mIsPasswordView = isPasswordView; } @@ -330,122 +343,200 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final String EVENT_TYPE_KEY = "_ty"; private static final Object[] EVENTKEYS_NULLVALUES = {}; + private LogUnit mCurrentLogUnit = new LogUnit(); + /** - * Write a description of the event out to the ResearchLog. + * Buffer a research log event, flagging it as privacy-sensitive. * - * Runs in the background to avoid blocking the UI thread. + * This event contains potentially private information. If the word that this event is a part + * of is determined to be privacy-sensitive, then this event should not be included in the + * output log. The system waits to output until the containing word is known. * * @param keys an array containing a descriptive name for the event, followed by the keys * @param values an array of values, either a String or Number. length should be one * less than the keys array */ - private synchronized void writeEvent(final String[] keys, final Object[] values) { + private synchronized void enqueuePotentiallyPrivateEvent(final String[] keys, + final Object[] values) { assert values.length + 1 == keys.length; + mCurrentLogUnit.addLogAtom(keys, values, true); + } + + /** + * Buffer a research log event, flaggint it as not privacy-sensitive. + * + * This event contains no potentially private information. Even if the word that this event + * is privacy-sensitive, this event can still safely be sent to the output log. The system + * waits until the containing word is known so that this event can be written in the proper + * temporal order with other events that may be privacy sensitive. + * + * @param keys an array containing a descriptive name for the event, followed by the keys + * @param values an array of values, either a String or Number. length should be one + * less than the keys array + */ + private synchronized void enqueueEvent(final String[] keys, final Object[] values) { + assert values.length + 1 == keys.length; + mCurrentLogUnit.addLogAtom(keys, values, false); + } + + private boolean isInDictionary(CharSequence word) { + return (mDictionary != null) && (mDictionary.isValidWord(word)); + } + + /** + * Write out enqueued LogEvents to the log, filtered for privacy. + * + * If word is in the dictionary, then it is not privacy-sensitive and all LogEvents related to + * it can be written to the log. If the word is not in the dictionary, then it may correspond + * to a proper name, which might reveal private information, so neither the word nor any + * information related to the word (e.g. the down/motion/up coordinates) should be revealed. + * These LogEvents have been marked as privacy-sensitive; non privacy-sensitive events are still + * written out. + * + * @param word the word to be checked for inclusion in the dictionary + */ + /* package for test */ synchronized void flushQueue(CharSequence word) { if (isAllowedToLog()) { - mLoggingHandler.post(new Runnable() { - @Override - public void run() { - try { - mJsonWriter.beginObject(); - mJsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis()); - mJsonWriter.name(UPTIME_KEY).value(SystemClock.uptimeMillis()); - mJsonWriter.name(EVENT_TYPE_KEY).value(keys[0]); - final int length = values.length; - for (int i = 0; i < length; i++) { - mJsonWriter.name(keys[i + 1]); - Object value = values[i]; - if (value instanceof String) { - mJsonWriter.value((String) value); - } else if (value instanceof Number) { - mJsonWriter.value((Number) value); - } else if (value instanceof Boolean) { - mJsonWriter.value((Boolean) value); - } else if (value instanceof CompletionInfo[]) { - CompletionInfo[] ci = (CompletionInfo[]) value; - mJsonWriter.beginArray(); - for (int j = 0; j < ci.length; j++) { - mJsonWriter.value(scrubDigitsFromString(ci[j].toString())); - } - mJsonWriter.endArray(); - } else if (value instanceof SharedPreferences) { - SharedPreferences prefs = (SharedPreferences) value; - mJsonWriter.beginObject(); - for (Map.Entry entry : prefs.getAll().entrySet()) { - mJsonWriter.name(entry.getKey()); - final Object innerValue = entry.getValue(); - if (innerValue == null) { - mJsonWriter.nullValue(); - } else if (innerValue instanceof Boolean) { - mJsonWriter.value((Boolean) innerValue); - } else if (innerValue instanceof Number) { - mJsonWriter.value((Number) innerValue); - } else { - mJsonWriter.value(innerValue.toString()); - } - } - mJsonWriter.endObject(); - } else if (value instanceof Key[]) { - Key[] keys = (Key[]) value; - mJsonWriter.beginArray(); - for (Key key : keys) { - mJsonWriter.beginObject(); - mJsonWriter.name("code").value(key.mCode); - mJsonWriter.name("altCode").value(key.mAltCode); - mJsonWriter.name("x").value(key.mX); - mJsonWriter.name("y").value(key.mY); - mJsonWriter.name("w").value(key.mWidth); - mJsonWriter.name("h").value(key.mHeight); - mJsonWriter.endObject(); - } - mJsonWriter.endArray(); - } else if (value instanceof SuggestedWords) { - SuggestedWords words = (SuggestedWords) value; - mJsonWriter.beginObject(); - mJsonWriter.name("typedWordValid").value(words.mTypedWordValid); - mJsonWriter.name("hasAutoCorrectionCandidate") - .value(words.mHasAutoCorrectionCandidate); - mJsonWriter.name("isPunctuationSuggestions") - .value(words.mIsPunctuationSuggestions); - mJsonWriter.name("allowsToBeAutoCorrected") - .value(words.mAllowsToBeAutoCorrected); - mJsonWriter.name("isObsoleteSuggestions") - .value(words.mIsObsoleteSuggestions); - mJsonWriter.name("isPrediction") - .value(words.mIsPrediction); - mJsonWriter.name("words"); - mJsonWriter.beginArray(); - final int size = words.size(); - for (int j = 0; j < size; j++) { - SuggestedWordInfo wordInfo = words.getWordInfo(j); - mJsonWriter.value(scrubDigitsFromString(wordInfo.toString())); - } - mJsonWriter.endArray(); - mJsonWriter.endObject(); - } else if (value == null) { - mJsonWriter.nullValue(); - } else { - Log.w(TAG, "Unrecognized type to be logged: " + - (value == null ? "" : value.getClass().getName())); - mJsonWriter.nullValue(); - } + // check for dictionary + if (mDictionary == null && mSuggest != null && mSuggest.hasMainDictionary()) { + mDictionary = mSuggest.getMainDictionary(); + } + mCurrentLogUnit.setIsPrivacySafe(word != null && isInDictionary(word)); + mLoggingHandler.post(mCurrentLogUnit); + mCurrentLogUnit = new LogUnit(); + } + } + + private synchronized void outputEvent(final String[] keys, final Object[] values) { + try { + mJsonWriter.beginObject(); + mJsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis()); + mJsonWriter.name(UPTIME_KEY).value(SystemClock.uptimeMillis()); + mJsonWriter.name(EVENT_TYPE_KEY).value(keys[0]); + final int length = values.length; + for (int i = 0; i < length; i++) { + mJsonWriter.name(keys[i + 1]); + Object value = values[i]; + if (value instanceof String) { + mJsonWriter.value((String) value); + } else if (value instanceof Number) { + mJsonWriter.value((Number) value); + } else if (value instanceof Boolean) { + mJsonWriter.value((Boolean) value); + } else if (value instanceof CompletionInfo[]) { + CompletionInfo[] ci = (CompletionInfo[]) value; + mJsonWriter.beginArray(); + for (int j = 0; j < ci.length; j++) { + mJsonWriter.value(ci[j].toString()); + } + mJsonWriter.endArray(); + } else if (value instanceof SharedPreferences) { + SharedPreferences prefs = (SharedPreferences) value; + mJsonWriter.beginObject(); + for (Map.Entry entry : prefs.getAll().entrySet()) { + mJsonWriter.name(entry.getKey()); + final Object innerValue = entry.getValue(); + if (innerValue == null) { + mJsonWriter.nullValue(); + } else if (innerValue instanceof Boolean) { + mJsonWriter.value((Boolean) innerValue); + } else if (innerValue instanceof Number) { + mJsonWriter.value((Number) innerValue); + } else { + mJsonWriter.value(innerValue.toString()); } + } + mJsonWriter.endObject(); + } else if (value instanceof Key[]) { + Key[] keyboardKeys = (Key[]) value; + mJsonWriter.beginArray(); + for (Key keyboardKey : keyboardKeys) { + mJsonWriter.beginObject(); + mJsonWriter.name("code").value(keyboardKey.mCode); + mJsonWriter.name("altCode").value(keyboardKey.mAltCode); + mJsonWriter.name("x").value(keyboardKey.mX); + mJsonWriter.name("y").value(keyboardKey.mY); + mJsonWriter.name("w").value(keyboardKey.mWidth); + mJsonWriter.name("h").value(keyboardKey.mHeight); mJsonWriter.endObject(); - } catch (IOException e) { - e.printStackTrace(); - Log.w(TAG, "Error in JsonWriter; disabling logging"); - try { - mJsonWriter.close(); - } catch (IllegalStateException e1) { - // assume that this is just the json not being terminated properly. - // ignore - } catch (IOException e1) { - e1.printStackTrace(); - } finally { - mJsonWriter = NULL_JSON_WRITER; - } } + mJsonWriter.endArray(); + } else if (value instanceof SuggestedWords) { + SuggestedWords words = (SuggestedWords) value; + mJsonWriter.beginObject(); + mJsonWriter.name("typedWordValid").value(words.mTypedWordValid); + mJsonWriter.name("hasAutoCorrectionCandidate") + .value(words.mHasAutoCorrectionCandidate); + mJsonWriter.name("isPunctuationSuggestions") + .value(words.mIsPunctuationSuggestions); + mJsonWriter.name("allowsToBeAutoCorrected") + .value(words.mAllowsToBeAutoCorrected); + mJsonWriter.name("isObsoleteSuggestions") + .value(words.mIsObsoleteSuggestions); + mJsonWriter.name("isPrediction") + .value(words.mIsPrediction); + mJsonWriter.name("words"); + mJsonWriter.beginArray(); + final int size = words.size(); + for (int j = 0; j < size; j++) { + SuggestedWordInfo wordInfo = words.getWordInfo(j); + mJsonWriter.value(wordInfo.toString()); + } + mJsonWriter.endArray(); + mJsonWriter.endObject(); + } else if (value == null) { + mJsonWriter.nullValue(); + } else { + Log.w(TAG, "Unrecognized type to be logged: " + + (value == null ? "" : value.getClass().getName())); + mJsonWriter.nullValue(); } - }); + } + mJsonWriter.endObject(); + } catch (IOException e) { + e.printStackTrace(); + Log.w(TAG, "Error in JsonWriter; disabling logging"); + try { + mJsonWriter.close(); + } catch (IllegalStateException e1) { + // assume that this is just the json not being terminated properly. + // ignore + } catch (IOException e1) { + e1.printStackTrace(); + } finally { + mJsonWriter = NULL_JSON_WRITER; + } + } + } + + private static class LogUnit implements Runnable { + private final List mKeysList = new ArrayList(); + private final List mValuesList = new ArrayList(); + private final List mIsPotentiallyPrivate = new ArrayList(); + private boolean mIsPrivacySafe = false; + + private void addLogAtom(final String[] keys, final Object[] values, + final Boolean isPotentiallyPrivate) { + mKeysList.add(keys); + mValuesList.add(values); + mIsPotentiallyPrivate.add(isPotentiallyPrivate); + } + + void setIsPrivacySafe(boolean isPrivacySafe) { + mIsPrivacySafe = isPrivacySafe; + } + + @Override + public void run() { + final int numAtoms = mKeysList.size(); + for (int atomIndex = 0; atomIndex < numAtoms; atomIndex++) { + if (!mIsPrivacySafe && mIsPotentiallyPrivate.get(atomIndex)) { + continue; + } + final String[] keys = mKeysList.get(atomIndex); + final Object[] values = mValuesList.get(atomIndex); + ResearchLogger.getInstance().outputEvent(keys, values); + } } } @@ -477,6 +568,16 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } + private String scrubWord(String word) { + if (mDictionary == null) { + return WORD_REPLACEMENT_STRING; + } + if (mDictionary.isValidWord(word)) { + return word; + } + return WORD_REPLACEMENT_STRING; + } + private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT = { "LatinKeyboardViewProcessMotionEvent", "action", "eventTime", "id", "x", "y", "size", "pressure" @@ -500,7 +601,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { actionString, eventTime, id, x, y, size, pressure }; - getInstance().writeEvent(EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT, values); + getInstance().enqueuePotentiallyPrivateEvent( + EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT, values); } } @@ -511,7 +613,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { Keyboard.printableCode(scrubDigitFromCodePoint(code)), x, y }; - getInstance().writeEvent(EVENTKEYS_LATINIME_ONCODEINPUT, values); + getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_ONCODEINPUT, values); } private static final String[] EVENTKEYS_CORRECTION = { @@ -522,7 +624,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { subgroup, scrubDigitsFromString(before), scrubDigitsFromString(after), position }; - getInstance().writeEvent(EVENTKEYS_CORRECTION, values); + getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_CORRECTION, values); } private static final String[] EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION = { @@ -533,7 +635,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { scrubDigitsFromString(typedWord), scrubDigitsFromString(autoCorrection) }; - getInstance().writeEvent(EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION, values); + final ResearchLogger researchLogger = getInstance(); + researchLogger.enqueuePotentiallyPrivateEvent( + EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION, values); + researchLogger.flushQueue(autoCorrection); } private static final String[] EVENTKEYS_LATINIME_COMMITTEXT = { @@ -543,7 +648,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { scrubDigitsFromString(typedWord.toString()) }; - getInstance().writeEvent(EVENTKEYS_LATINIME_COMMITTEXT, values); + final ResearchLogger researchLogger = getInstance(); + researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_COMMITTEXT, values); + researchLogger.flushQueue(typedWord); } private static final String[] EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT = { @@ -553,14 +660,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { length }; - getInstance().writeEvent(EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT, values); + getInstance().enqueueEvent(EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT, values); } private static final String[] EVENTKEYS_LATINIME_DOUBLESPACEAUTOPERIOD = { "LatinIMEDoubleSpaceAutoPeriod" }; public static void latinIME_doubleSpaceAutoPeriod() { - getInstance().writeEvent(EVENTKEYS_LATINIME_DOUBLESPACEAUTOPERIOD, EVENTKEYS_NULLVALUES); + getInstance().enqueueEvent(EVENTKEYS_LATINIME_DOUBLESPACEAUTOPERIOD, EVENTKEYS_NULLVALUES); } private static final String[] EVENTKEYS_LATINIME_ONDISPLAYCOMPLETIONS = { @@ -571,7 +678,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { applicationSpecifiedCompletions }; - getInstance().writeEvent(EVENTKEYS_LATINIME_ONDISPLAYCOMPLETIONS, values); + getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_ONDISPLAYCOMPLETIONS, + values); } /* package */ static boolean getAndClearLatinIMEExpectingUpdateSelection() { @@ -592,27 +700,35 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang ic.setSelection(savedSelectionStart, savedSelectionEnd); ic.endBatchEdit(); sLatinIMEExpectingUpdateSelection = true; - Object[] values = new Object[2]; - if (TextUtils.isEmpty(charSequence)) { - values[0] = false; - values[1] = ""; - } 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); - values[0] = true; - values[1] = scrubDigitsFromString(truncatedCharSequence.toString()); - } else { + final Object[] values = new Object[2]; + if (OUTPUT_ENTIRE_BUFFER) { + if (TextUtils.isEmpty(charSequence)) { values[0] = false; - values[1] = scrubDigitsFromString(charSequence.toString()); + values[1] = ""; + } 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); + values[0] = true; + values[1] = truncatedCharSequence.toString(); + } else { + values[0] = false; + values[1] = charSequence.toString(); + } } + } else { + values[0] = true; + values[1] = ""; } - getInstance().writeEvent(EVENTKEYS_LATINIME_ONWINDOWHIDDEN, values); + final ResearchLogger researchLogger = getInstance(); + researchLogger.enqueueEvent(EVENTKEYS_LATINIME_ONWINDOWHIDDEN, values); + researchLogger.flushQueue(null); } } @@ -628,7 +744,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang Integer.toHexString(editorInfo.imeOptions), editorInfo.fieldId, Build.DISPLAY, Build.MODEL, prefs, OUTPUT_FORMAT_VERSION }; - getInstance().writeEvent(EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL, values); + getInstance().enqueueEvent(EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL, values); } } @@ -662,12 +778,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang word = range.mWord; } } + final ResearchLogger researchLogger = getInstance(); + final String scrubbedWord = researchLogger.scrubWord(word); final Object[] values = { lastSelectionStart, lastSelectionEnd, oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, composingSpanEnd, expectingUpdateSelection, - expectingUpdateSelectionFromLogger, scrubDigitsFromString(word) + expectingUpdateSelectionFromLogger, scrubbedWord }; - getInstance().writeEvent(EVENTKEYS_LATINIME_ONUPDATESELECTION, values); + researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_ONUPDATESELECTION, values); } private static final String[] EVENTKEYS_LATINIME_PERFORMEDITORACTION = { @@ -677,7 +795,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { imeActionNext }; - getInstance().writeEvent(EVENTKEYS_LATINIME_PERFORMEDITORACTION, values); + getInstance().enqueueEvent(EVENTKEYS_LATINIME_PERFORMEDITORACTION, values); } private static final String[] EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION = { @@ -688,7 +806,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { index, cs, x, y }; - getInstance().writeEvent(EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION, values); + final ResearchLogger researchLogger = getInstance(); + researchLogger.enqueuePotentiallyPrivateEvent( + EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION, values); + researchLogger.flushQueue(cs.toString()); } private static final String[] EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY = { @@ -700,7 +821,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang scrubDigitsFromString(replacedWord), index, suggestion == null ? null : scrubDigitsFromString(suggestion.toString()), x, y }; - getInstance().writeEvent(EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY, values); + final ResearchLogger researchLogger = getInstance(); + researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY, + values); + researchLogger.flushQueue(suggestion.toString()); } private static final String[] EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION = { @@ -711,14 +835,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { index, suggestion, x, y }; - getInstance().writeEvent(EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION, values); + getInstance().enqueueEvent(EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION, values); } private static final String[] EVENTKEYS_LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT = { "LatinIMERevertDoubleSpaceWhileInBatchEdit" }; public static void latinIME_revertDoubleSpaceWhileInBatchEdit() { - getInstance().writeEvent(EVENTKEYS_LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT, + getInstance().enqueueEvent(EVENTKEYS_LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT, EVENTKEYS_NULLVALUES); } @@ -726,7 +850,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang "LatinIMERevertSwapPunctuation" }; public static void latinIME_revertSwapPunctuation() { - getInstance().writeEvent(EVENTKEYS_LATINIME_REVERTSWAPPUNCTUATION, EVENTKEYS_NULLVALUES); + getInstance().enqueueEvent(EVENTKEYS_LATINIME_REVERTSWAPPUNCTUATION, EVENTKEYS_NULLVALUES); } private static final String[] EVENTKEYS_LATINIME_SENDKEYCODEPOINT = { @@ -736,14 +860,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { Keyboard.printableCode(scrubDigitFromCodePoint(code)) }; - getInstance().writeEvent(EVENTKEYS_LATINIME_SENDKEYCODEPOINT, values); + getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_SENDKEYCODEPOINT, values); } private static final String[] EVENTKEYS_LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT = { "LatinIMESwapSwapperAndSpaceWhileInBatchEdit" }; public static void latinIME_swapSwapperAndSpaceWhileInBatchEdit() { - getInstance().writeEvent(EVENTKEYS_LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT, + getInstance().enqueueEvent(EVENTKEYS_LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT, EVENTKEYS_NULLVALUES); } @@ -751,14 +875,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang "LatinIMESwitchToKeyboardView" }; public static void latinIME_switchToKeyboardView() { - getInstance().writeEvent(EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW, EVENTKEYS_NULLVALUES); + getInstance().enqueueEvent(EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW, EVENTKEYS_NULLVALUES); } private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS = { "LatinKeyboardViewOnLongPress" }; public static void latinKeyboardView_onLongPress() { - getInstance().writeEvent(EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS, EVENTKEYS_NULLVALUES); + getInstance().enqueueEvent(EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS, EVENTKEYS_NULLVALUES); } private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD = { @@ -790,7 +914,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang keyboard.mOccupiedHeight, keyboard.mKeys }; - getInstance().writeEvent(EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD, values); + getInstance().enqueueEvent(EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD, values); getInstance().setIsPasswordView(isPasswordView); } } @@ -802,14 +926,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { originallyTypedWord }; - getInstance().writeEvent(EVENTKEYS_LATINIME_REVERTCOMMIT, values); + getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_REVERTCOMMIT, values); } private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONCANCELINPUT = { "PointerTrackerCallListenerOnCancelInput" }; public static void pointerTracker_callListenerOnCancelInput() { - getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONCANCELINPUT, + getInstance().enqueueEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONCANCELINPUT, EVENTKEYS_NULLVALUES); } @@ -827,7 +951,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang : scrubDigitsFromString(outputText.toString()), x, y, ignoreModifierKey, altersCode, key.isEnabled() }; - getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONCODEINPUT, values); + getInstance().enqueuePotentiallyPrivateEvent( + EVENTKEYS_POINTERTRACKER_CALLLISTENERONCODEINPUT, values); } } @@ -842,7 +967,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang Keyboard.printableCode(scrubDigitFromCodePoint(primaryCode)), withSliding, ignoreModifierKey, key.isEnabled() }; - getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONRELEASE, values); + getInstance().enqueuePotentiallyPrivateEvent( + EVENTKEYS_POINTERTRACKER_CALLLISTENERONRELEASE, values); } } @@ -853,7 +979,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { deltaT, distanceSquared }; - getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_ONDOWNEVENT, values); + getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_POINTERTRACKER_ONDOWNEVENT, values); } private static final String[] EVENTKEYS_POINTERTRACKER_ONMOVEEVENT = { @@ -864,7 +990,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { x, y, lastX, lastY }; - getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_ONMOVEEVENT, values); + getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_POINTERTRACKER_ONMOVEEVENT, values); } private static final String[] EVENTKEYS_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT = { @@ -875,8 +1001,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { me.toString() }; - getInstance().writeEvent(EVENTKEYS_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT, - values); + getInstance().enqueuePotentiallyPrivateEvent( + EVENTKEYS_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT, values); } } @@ -888,7 +1014,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final Object[] values = { suggestedWords }; - getInstance().writeEvent(EVENTKEYS_SUGGESTIONSVIEW_SETSUGGESTIONS, values); + getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_SUGGESTIONSVIEW_SETSUGGESTIONS, + values); } } @@ -896,6 +1023,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang "UserTimestamp" }; public void userTimestamp() { - getInstance().writeEvent(EVENTKEYS_USER_TIMESTAMP, EVENTKEYS_NULLVALUES); + getInstance().enqueueEvent(EVENTKEYS_USER_TIMESTAMP, EVENTKEYS_NULLVALUES); } } diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 68b7b913f..7398c82fa 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -65,7 +65,7 @@ public class Suggest implements Dictionary.WordCallback { private static final boolean DBG = LatinImeLogger.sDBG; - private boolean mHasMainDictionary; + private Dictionary mMainDictionary; private ContactsBinaryDictionary mContactsDict; private WhitelistDictionary mWhiteListDictionary; private final ConcurrentHashMap mUnigramDictionaries = @@ -98,7 +98,7 @@ public class Suggest implements Dictionary.WordCallback { final long startOffset, final long length, final Locale locale) { final Dictionary mainDict = DictionaryFactory.createDictionaryForTest(context, dictionary, startOffset, length /* useFullEditDistance */, false, locale); - mHasMainDictionary = null != mainDict; + mMainDictionary = mainDict; addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, mainDict); addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, mainDict); initWhitelistAndAutocorrectAndPool(context, locale); @@ -129,15 +129,15 @@ public class Suggest implements Dictionary.WordCallback { } public void resetMainDict(final Context context, final Locale locale) { - mHasMainDictionary = false; + mMainDictionary = null; new Thread("InitializeBinaryDictionary") { @Override public void run() { final DictionaryCollection newMainDict = DictionaryFactory.createMainDictionaryFromManager(context, locale); - mHasMainDictionary = null != newMainDict && !newMainDict.isEmpty(); addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, newMainDict); addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, newMainDict); + mMainDictionary = newMainDict; } }.start(); } @@ -145,7 +145,11 @@ public class Suggest implements Dictionary.WordCallback { // The main dictionary could have been loaded asynchronously. Don't cache the return value // of this method. public boolean hasMainDictionary() { - return mHasMainDictionary; + return null != mMainDictionary && mMainDictionary.isInitialized(); + } + + public Dictionary getMainDictionary() { + return mMainDictionary; } public ContactsBinaryDictionary getContactsDictionary() { @@ -365,7 +369,7 @@ public class Suggest implements Dictionary.WordCallback { // language, and it will unexpectedly auto-correct. For example, if the user types in // English with no dictionary and has a "Will" in their contact list, "will" would // always auto-correct to "Will" which is unwanted. Hence, no main dict => no auto-correct. - && mHasMainDictionary; + && hasMainDictionary(); boolean autoCorrectionAvailable = hasAutoCorrection; if (correctionMode == CORRECTION_FULL || correctionMode == CORRECTION_FULL_BIGRAM) { @@ -511,7 +515,7 @@ public class Suggest implements Dictionary.WordCallback { for (final Dictionary dictionary : dictionaries) { dictionary.close(); } - mHasMainDictionary = false; + mMainDictionary = null; } // TODO: Resolve the inconsistencies between the native auto correction algorithms and -- cgit v1.2.3-83-g751a From 33d9f9b6dbafba97d5f46b021727b9d797906baa Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Mon, 18 Jun 2012 17:48:00 -0700 Subject: Allow punctuation through privacy filter Also cleaned up the privacy code a bit. multi-project commit with Change-Id: Ic0919a6929ebb2623ff4124f7adc96d9e5f8df3c Bug: 6188932 Change-Id: Id470fe7cc6e4a8fb01f1ea5b178a74cd27d59218 --- .../android/inputmethod/latin/ResearchLogger.java | 73 +++++++++++++--------- 1 file changed, 44 insertions(+), 29 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index ee596924f..cf3cc7873 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -379,29 +379,43 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mCurrentLogUnit.addLogAtom(keys, values, false); } - private boolean isInDictionary(CharSequence word) { - return (mDictionary != null) && (mDictionary.isValidWord(word)); + /* package for test */ boolean isPrivacyThreat(String word) { + // currently: word not in dictionary or contains numbers. + if (TextUtils.isEmpty(word)) { + return false; + } + final int length = word.length(); + boolean hasLetter = false; + for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) { + final int codePoint = Character.codePointAt(word, i); + if (Character.isDigit(codePoint)) { + return true; + } + if (Character.isLetter(codePoint)) { + hasLetter = true; + break; // Word may contain digits, but will only be allowed if in the dictionary. + } + } + if (hasLetter) { + if (mDictionary == null && mSuggest != null && mSuggest.hasMainDictionary()) { + mDictionary = mSuggest.getMainDictionary(); + } + if (mDictionary == null) { + // Can't access dictionary. Assume privacy threat. + return true; + } + return !(mDictionary.isValidWord(word)); + } + // No letters, no numbers. Punctuation, space, or something else. + return false; } /** - * Write out enqueued LogEvents to the log, filtered for privacy. - * - * If word is in the dictionary, then it is not privacy-sensitive and all LogEvents related to - * it can be written to the log. If the word is not in the dictionary, then it may correspond - * to a proper name, which might reveal private information, so neither the word nor any - * information related to the word (e.g. the down/motion/up coordinates) should be revealed. - * These LogEvents have been marked as privacy-sensitive; non privacy-sensitive events are still - * written out. - * - * @param word the word to be checked for inclusion in the dictionary + * Write out enqueued LogEvents to the log, possibly dropping privacy sensitive events. */ - /* package for test */ synchronized void flushQueue(CharSequence word) { + /* package for test */ synchronized void flushQueue(boolean removePotentiallyPrivateEvents) { if (isAllowedToLog()) { - // check for dictionary - if (mDictionary == null && mSuggest != null && mSuggest.hasMainDictionary()) { - mDictionary = mSuggest.getMainDictionary(); - } - mCurrentLogUnit.setIsPrivacySafe(word != null && isInDictionary(word)); + mCurrentLogUnit.setRemovePotentiallyPrivateEvents(removePotentiallyPrivateEvents); mLoggingHandler.post(mCurrentLogUnit); mCurrentLogUnit = new LogUnit(); } @@ -513,7 +527,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private final List mKeysList = new ArrayList(); private final List mValuesList = new ArrayList(); private final List mIsPotentiallyPrivate = new ArrayList(); - private boolean mIsPrivacySafe = false; + private boolean mRemovePotentiallyPrivateEvents = true; private void addLogAtom(final String[] keys, final Object[] values, final Boolean isPotentiallyPrivate) { @@ -522,15 +536,15 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mIsPotentiallyPrivate.add(isPotentiallyPrivate); } - void setIsPrivacySafe(boolean isPrivacySafe) { - mIsPrivacySafe = isPrivacySafe; + void setRemovePotentiallyPrivateEvents(boolean removePotentiallyPrivateEvents) { + mRemovePotentiallyPrivateEvents = removePotentiallyPrivateEvents; } @Override public void run() { final int numAtoms = mKeysList.size(); for (int atomIndex = 0; atomIndex < numAtoms; atomIndex++) { - if (!mIsPrivacySafe && mIsPotentiallyPrivate.get(atomIndex)) { + if (mRemovePotentiallyPrivateEvents && mIsPotentiallyPrivate.get(atomIndex)) { continue; } final String[] keys = mKeysList.get(atomIndex); @@ -548,7 +562,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang StringBuilder sb = null; final int length = s.length(); for (int i = 0; i < length; i = s.offsetByCodePoints(i, 1)) { - int codePoint = Character.codePointAt(s, i); + final int codePoint = Character.codePointAt(s, i); if (Character.isDigit(codePoint)) { if (sb == null) { sb = new StringBuilder(length); @@ -638,19 +652,20 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final ResearchLogger researchLogger = getInstance(); researchLogger.enqueuePotentiallyPrivateEvent( EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION, values); - researchLogger.flushQueue(autoCorrection); + researchLogger.flushQueue(researchLogger.isPrivacyThreat(autoCorrection)); } private static final String[] EVENTKEYS_LATINIME_COMMITTEXT = { "LatinIMECommitText", "typedWord" }; public static void latinIME_commitText(final CharSequence typedWord) { + final String scrubbedWord = scrubDigitsFromString(typedWord.toString()); final Object[] values = { - scrubDigitsFromString(typedWord.toString()) + scrubbedWord }; final ResearchLogger researchLogger = getInstance(); researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_COMMITTEXT, values); - researchLogger.flushQueue(typedWord); + researchLogger.flushQueue(researchLogger.isPrivacyThreat(scrubbedWord)); } private static final String[] EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT = { @@ -728,7 +743,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } final ResearchLogger researchLogger = getInstance(); researchLogger.enqueueEvent(EVENTKEYS_LATINIME_ONWINDOWHIDDEN, values); - researchLogger.flushQueue(null); + researchLogger.flushQueue(true); // Play it safe. Remove privacy-sensitive events. } } @@ -809,7 +824,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final ResearchLogger researchLogger = getInstance(); researchLogger.enqueuePotentiallyPrivateEvent( EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION, values); - researchLogger.flushQueue(cs.toString()); + researchLogger.flushQueue(researchLogger.isPrivacyThreat(cs.toString())); } private static final String[] EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY = { @@ -824,7 +839,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final ResearchLogger researchLogger = getInstance(); researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY, values); - researchLogger.flushQueue(suggestion.toString()); + researchLogger.flushQueue(researchLogger.isPrivacyThreat(suggestion.toString())); } private static final String[] EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION = { -- cgit v1.2.3-83-g751a From e961188e9fd4f4365c6c745c8d3d838dd7dfe6a0 Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Wed, 20 Jun 2012 20:23:19 -0700 Subject: only output every kth word to log multi-project CL with Ib5b544b9b2d8b0e4419238976b2e274e5ac564f8 Bug: 6188932 Change-Id: Iea68cf36924d6fda126130a98431a6ce02ba251e --- .../android/inputmethod/latin/ResearchLogger.java | 66 +++++++++++++++++++--- 1 file changed, 58 insertions(+), 8 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index cf3cc7873..df8892911 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -197,6 +197,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang Log.d(TAG, "stop called"); if (mLoggingHandler != null && mLoggingState == LOGGING_STATE_ON) { mLoggingState = LOGGING_STATE_STOPPING; + flushEventQueue(true); // put this in the Handler queue so pending writes are processed first. mLoggingHandler.post(new Runnable() { @Override @@ -379,11 +380,52 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mCurrentLogUnit.addLogAtom(keys, values, false); } + // Used to track how often words are logged. Too-frequent logging can leak + // semantics, disclosing private data. + /* package for test */ static class LoggingFrequencyState { + private static final int DEFAULT_WORD_LOG_FREQUENCY = 10; + private int mWordsRemainingToSkip; + private final int mFrequency; + + /** + * Tracks how often words may be uploaded. + * + * @param frequency 1=Every word, 2=Every other word, etc. + */ + public LoggingFrequencyState(int frequency) { + mFrequency = frequency; + mWordsRemainingToSkip = mFrequency; + } + + public void onWordLogged() { + mWordsRemainingToSkip = mFrequency; + } + + public void onWordNotLogged() { + if (mWordsRemainingToSkip > 1) { + mWordsRemainingToSkip--; + } + } + + public boolean isSafeToLog() { + return mWordsRemainingToSkip <= 1; + } + } + + /* package for test */ LoggingFrequencyState mLoggingFrequencyState = + new LoggingFrequencyState(LoggingFrequencyState.DEFAULT_WORD_LOG_FREQUENCY); + /* package for test */ boolean isPrivacyThreat(String word) { - // currently: word not in dictionary or contains numbers. + // Current checks: + // - Word not in dictionary + // - Word contains numbers + // - Privacy-safe word not logged recently if (TextUtils.isEmpty(word)) { return false; } + if (!mLoggingFrequencyState.isSafeToLog()) { + return true; + } final int length = word.length(); boolean hasLetter = false; for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) { @@ -410,15 +452,26 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang return false; } + private void onWordComplete(String word) { + final boolean isPrivacyThreat = isPrivacyThreat(word); + flushEventQueue(isPrivacyThreat); + if (isPrivacyThreat) { + mLoggingFrequencyState.onWordNotLogged(); + } else { + mLoggingFrequencyState.onWordLogged(); + } + } + /** * Write out enqueued LogEvents to the log, possibly dropping privacy sensitive events. */ - /* package for test */ synchronized void flushQueue(boolean removePotentiallyPrivateEvents) { + /* package for test */ synchronized void flushEventQueue( + boolean removePotentiallyPrivateEvents) { if (isAllowedToLog()) { mCurrentLogUnit.setRemovePotentiallyPrivateEvents(removePotentiallyPrivateEvents); mLoggingHandler.post(mCurrentLogUnit); - mCurrentLogUnit = new LogUnit(); } + mCurrentLogUnit = new LogUnit(); } private synchronized void outputEvent(final String[] keys, final Object[] values) { @@ -652,7 +705,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final ResearchLogger researchLogger = getInstance(); researchLogger.enqueuePotentiallyPrivateEvent( EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION, values); - researchLogger.flushQueue(researchLogger.isPrivacyThreat(autoCorrection)); } private static final String[] EVENTKEYS_LATINIME_COMMITTEXT = { @@ -665,7 +717,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang }; final ResearchLogger researchLogger = getInstance(); researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_COMMITTEXT, values); - researchLogger.flushQueue(researchLogger.isPrivacyThreat(scrubbedWord)); + researchLogger.onWordComplete(scrubbedWord); } private static final String[] EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT = { @@ -743,7 +795,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } final ResearchLogger researchLogger = getInstance(); researchLogger.enqueueEvent(EVENTKEYS_LATINIME_ONWINDOWHIDDEN, values); - researchLogger.flushQueue(true); // Play it safe. Remove privacy-sensitive events. + researchLogger.flushEventQueue(true); // Play it safe. Remove privacy-sensitive events. } } @@ -824,7 +876,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final ResearchLogger researchLogger = getInstance(); researchLogger.enqueuePotentiallyPrivateEvent( EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION, values); - researchLogger.flushQueue(researchLogger.isPrivacyThreat(cs.toString())); } private static final String[] EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY = { @@ -839,7 +890,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final ResearchLogger researchLogger = getInstance(); researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY, values); - researchLogger.flushQueue(researchLogger.isPrivacyThreat(suggestion.toString())); } private static final String[] EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION = { -- cgit v1.2.3-83-g751a From 4f444410f29315d7c7baf9d4e33acf912d0fa876 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Thu, 28 Jun 2012 18:32:18 +0900 Subject: Remove a useless variable (A28) Change-Id: I1058123d233540fb72a94028987a43740224f635 --- java/src/com/android/inputmethod/latin/ResearchLogger.java | 2 -- java/src/com/android/inputmethod/latin/SuggestedWords.java | 3 --- 2 files changed, 5 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index df8892911..79e1d376c 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -536,8 +536,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang .value(words.mHasAutoCorrectionCandidate); mJsonWriter.name("isPunctuationSuggestions") .value(words.mIsPunctuationSuggestions); - mJsonWriter.name("allowsToBeAutoCorrected") - .value(words.mAllowsToBeAutoCorrected); mJsonWriter.name("isObsoleteSuggestions") .value(words.mIsObsoleteSuggestions); mJsonWriter.name("isPrediction") diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index f6926f3bb..a740d9ce7 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -30,7 +30,6 @@ public class SuggestedWords { public final boolean mTypedWordValid; public final boolean mHasAutoCorrectionCandidate; public final boolean mIsPunctuationSuggestions; - public final boolean mAllowsToBeAutoCorrected; public final boolean mIsObsoleteSuggestions; public final boolean mIsPrediction; private final ArrayList mSuggestedWordInfoList; @@ -45,7 +44,6 @@ public class SuggestedWords { mSuggestedWordInfoList = suggestedWordInfoList; mTypedWordValid = typedWordValid; mHasAutoCorrectionCandidate = hasAutoCorrectionCandidate; - mAllowsToBeAutoCorrected = allowsToBeAutoCorrected; mIsPunctuationSuggestions = isPunctuationSuggestions; mIsObsoleteSuggestions = isObsoleteSuggestions; mIsPrediction = isPrediction; @@ -81,7 +79,6 @@ public class SuggestedWords { return "SuggestedWords:" + " mTypedWordValid=" + mTypedWordValid + " mHasAutoCorrectionCandidate=" + mHasAutoCorrectionCandidate - + " mAllowsToBeAutoCorrected=" + mAllowsToBeAutoCorrected + " mIsPunctuationSuggestions=" + mIsPunctuationSuggestions + " words=" + Arrays.toString(mSuggestedWordInfoList.toArray()); } -- cgit v1.2.3-83-g751a From 84074cf503f67737bcfd335a775553763bd8e033 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Thu, 28 Jun 2012 19:41:27 +0900 Subject: Update log and make a variable private (A35). Change-Id: Ib4a8f41dc5941bce46402e1a41a6c21dccb0601f --- java/src/com/android/inputmethod/latin/ResearchLogger.java | 3 +-- java/src/com/android/inputmethod/latin/SuggestedWords.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/ResearchLogger.java') diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index 79e1d376c..e83d7c84a 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -532,8 +532,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang SuggestedWords words = (SuggestedWords) value; mJsonWriter.beginObject(); mJsonWriter.name("typedWordValid").value(words.mTypedWordValid); - mJsonWriter.name("hasAutoCorrectionCandidate") - .value(words.mHasAutoCorrectionCandidate); + mJsonWriter.name("willAutoCorrect").value(words.mWillAutoCorrect); mJsonWriter.name("isPunctuationSuggestions") .value(words.mIsPunctuationSuggestions); mJsonWriter.name("isObsoleteSuggestions") diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index b84820cb8..b980e482d 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -28,7 +28,7 @@ public class SuggestedWords { new ArrayList(0), false, false, false, false, false); public final boolean mTypedWordValid; - public final boolean mHasAutoCorrectionCandidate; + private final boolean mHasAutoCorrectionCandidate; public final boolean mWillAutoCorrect; public final boolean mIsPunctuationSuggestions; public final boolean mIsObsoleteSuggestions; -- cgit v1.2.3-83-g751a