diff options
Diffstat (limited to 'java/src')
5 files changed, 57 insertions, 16 deletions
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index e9347461c..79a05ceae 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -563,6 +563,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction } mSettings.onDestroy(); unregisterReceiver(mReceiver); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.getInstance().onDestroy(); + } // TODO: The experimental version is not supported by the Dictionary Pack Service yet. if (!ProductionFlag.IS_EXPERIMENTAL) { unregisterReceiver(mDictionaryPackInstallReceiver); diff --git a/java/src/com/android/inputmethod/research/LogUnit.java b/java/src/com/android/inputmethod/research/LogUnit.java index e91976a03..839e2b7ba 100644 --- a/java/src/com/android/inputmethod/research/LogUnit.java +++ b/java/src/com/android/inputmethod/research/LogUnit.java @@ -16,7 +16,6 @@ package com.android.inputmethod.research; -import android.content.SharedPreferences; import android.os.SystemClock; import android.text.TextUtils; import android.util.JsonWriter; @@ -45,7 +44,7 @@ import java.util.List; * will not violate the user's privacy. Checks for this may include whether other LogUnits have * been published recently, or whether the LogUnit contains numbers, etc. */ -/* package */ class LogUnit { +public class LogUnit { private static final String TAG = LogUnit.class.getSimpleName(); private static final boolean DEBUG = false && ProductionFlag.IS_EXPERIMENTAL_DEBUG; diff --git a/java/src/com/android/inputmethod/research/MainLogBuffer.java b/java/src/com/android/inputmethod/research/MainLogBuffer.java index 45b83dd76..9e77a1a38 100644 --- a/java/src/com/android/inputmethod/research/MainLogBuffer.java +++ b/java/src/com/android/inputmethod/research/MainLogBuffer.java @@ -18,6 +18,7 @@ package com.android.inputmethod.research; import android.util.Log; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.Suggest; import com.android.inputmethod.latin.define.ProductionFlag; @@ -64,7 +65,11 @@ public abstract class MainLogBuffer extends FixedLogBuffer { // The size of the n-grams logged. E.g. N_GRAM_SIZE = 2 means to sample bigrams. public static final int N_GRAM_SIZE = 2; + // TODO: Remove dependence on Suggest, and pass in Dictionary as a parameter to an appropriate + // method. private Suggest mSuggest; + @UsedForTesting + private Dictionary mDictionaryForTesting; private boolean mIsStopping = false; /* package for test */ int mNumWordsBetweenNGrams; @@ -83,7 +88,15 @@ public abstract class MainLogBuffer extends FixedLogBuffer { mSuggest = suggest; } + @UsedForTesting + /* package for test */ void setDictionaryForTesting(final Dictionary dictionary) { + mDictionaryForTesting = dictionary; + } + private Dictionary getDictionary() { + if (mDictionaryForTesting != null) { + return mDictionaryForTesting; + } if (mSuggest == null || !mSuggest.hasMainDictionary()) return null; return mSuggest.getMainDictionary(); } diff --git a/java/src/com/android/inputmethod/research/ResearchLog.java b/java/src/com/android/inputmethod/research/ResearchLog.java index 99d84938f..9016e23b3 100644 --- a/java/src/com/android/inputmethod/research/ResearchLog.java +++ b/java/src/com/android/inputmethod/research/ResearchLog.java @@ -38,12 +38,19 @@ import java.util.concurrent.TimeUnit; /** * 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 class logs operations on the IME keyboard, including what the user has typed. Data is + * written to a {@link JsonWriter}, which will write to a local file. + * + * The JsonWriter is created on-demand by calling {@link #getInitializedJsonWriterLocked}. + * + * This class uses an executor to perform file-writing operations on a separate thread. It also + * tries to avoid creating unnecessary files if there is nothing to write. It also handles + * flushing, making sure it happens, but not too frequently. * * This functionality is off by default. See {@link ProductionFlag#IS_EXPERIMENTAL}. */ public class ResearchLog { + // TODO: Automatically initialize the JsonWriter rather than requiring the caller to manage it. private static final String TAG = ResearchLog.class.getSimpleName(); private static final boolean DEBUG = false && ProductionFlag.IS_EXPERIMENTAL_DEBUG; private static final long FLUSH_DELAY_IN_MS = 1000 * 5; @@ -87,6 +94,12 @@ public class ResearchLog { mContext = context; } + /** + * Waits for any publication requests to finish and closes the {@link JsonWriter} used for + * output. + * + * See class comment for details about {@code JsonWriter} construction. + */ public synchronized void close(final Runnable onClosed) { mExecutor.submit(new Callable<Object>() { @Override @@ -94,20 +107,15 @@ public class ResearchLog { try { if (mHasWrittenData) { mJsonWriter.endArray(); - mJsonWriter.flush(); - mJsonWriter.close(); - if (DEBUG) { - Log.d(TAG, "wrote log to " + mFile); - } mHasWrittenData = false; - } else { - if (DEBUG) { - Log.d(TAG, "close() called, but no data, not outputting"); - } + } + mJsonWriter.flush(); + mJsonWriter.close(); + if (DEBUG) { + Log.d(TAG, "wrote log to " + mFile); } } catch (Exception e) { - Log.d(TAG, "error when closing ResearchLog:"); - e.printStackTrace(); + Log.d(TAG, "error when closing ResearchLog:", e); } finally { if (mFile != null && mFile.exists()) { mFile.setWritable(false, false); @@ -125,6 +133,12 @@ public class ResearchLog { private boolean mIsAbortSuccessful; + /** + * Waits for publication requests to finish, closes the {@link JsonWriter}, but then deletes the + * backing file used for output. + * + * See class comment for details about {@code JsonWriter} construction. + */ public synchronized void abort() { mExecutor.submit(new Callable<Object>() { @Override @@ -184,6 +198,12 @@ public class ResearchLog { mFlushFuture = mExecutor.schedule(mFlushCallable, FLUSH_DELAY_IN_MS, TimeUnit.MILLISECONDS); } + /** + * Queues up {@code logUnit} to be published in the background. + * + * @param logUnit the {@link LogUnit} to be published + * @param canIncludePrivateData whether private data in the LogUnit should be included + */ public synchronized void publish(final LogUnit logUnit, final boolean canIncludePrivateData) { try { mExecutor.submit(new Callable<Object>() { diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java index 25633d630..d9f37804d 100644 --- a/java/src/com/android/inputmethod/research/ResearchLogger.java +++ b/java/src/com/android/inputmethod/research/ResearchLogger.java @@ -208,7 +208,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private Intent mUploadIntent; private Intent mUploadNowIntent; - private LogUnit mCurrentLogUnit = new LogUnit(); + /* package for test */ LogUnit mCurrentLogUnit = new LogUnit(); // Gestured or tapped words may be committed after the gesture of the next word has started. // To ensure that the gesture data of the next word is not associated with the previous word, @@ -322,6 +322,12 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mMainKeyboardView = null; } + public void onDestroy() { + if (mPrefs != null) { + mPrefs.unregisterOnSharedPreferenceChangeListener(this); + } + } + private boolean hasSeenSplash() { return mPrefs.getBoolean(PREF_RESEARCH_HAS_SEEN_SPLASH, false); } |