aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/research/JsonUtils.java103
-rw-r--r--java/src/com/android/inputmethod/research/LogUnit.java84
-rw-r--r--java/src/com/android/inputmethod/research/ResearchLog.java105
3 files changed, 191 insertions, 101 deletions
diff --git a/java/src/com/android/inputmethod/research/JsonUtils.java b/java/src/com/android/inputmethod/research/JsonUtils.java
new file mode 100644
index 000000000..cb331d7f9
--- /dev/null
+++ b/java/src/com/android/inputmethod/research/JsonUtils.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.research;
+
+import android.content.SharedPreferences;
+import android.util.JsonWriter;
+import android.view.inputmethod.CompletionInfo;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+
+import java.io.IOException;
+import java.util.Map;
+
+/* package */ class JsonUtils {
+ private JsonUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ /* package */ static void writeJson(final CompletionInfo[] ci, final JsonWriter jsonWriter)
+ throws IOException {
+ jsonWriter.beginArray();
+ for (int j = 0; j < ci.length; j++) {
+ jsonWriter.value(ci[j].toString());
+ }
+ jsonWriter.endArray();
+ }
+
+ /* package */ static void writeJson(final SharedPreferences prefs, final JsonWriter jsonWriter)
+ throws IOException {
+ jsonWriter.beginObject();
+ for (Map.Entry<String,?> entry : prefs.getAll().entrySet()) {
+ jsonWriter.name(entry.getKey());
+ final Object innerValue = entry.getValue();
+ if (innerValue == null) {
+ jsonWriter.nullValue();
+ } else if (innerValue instanceof Boolean) {
+ jsonWriter.value((Boolean) innerValue);
+ } else if (innerValue instanceof Number) {
+ jsonWriter.value((Number) innerValue);
+ } else {
+ jsonWriter.value(innerValue.toString());
+ }
+ }
+ jsonWriter.endObject();
+ }
+
+ /* package */ static void writeJson(final Key[] keys, final JsonWriter jsonWriter)
+ throws IOException {
+ jsonWriter.beginArray();
+ for (Key key : keys) {
+ writeJson(key, jsonWriter);
+ }
+ jsonWriter.endArray();
+ }
+
+ private static void writeJson(final Key key, final JsonWriter jsonWriter) throws IOException {
+ jsonWriter.beginObject();
+ jsonWriter.name("code").value(key.mCode);
+ jsonWriter.name("altCode").value(key.getAltCode());
+ jsonWriter.name("x").value(key.mX);
+ jsonWriter.name("y").value(key.mY);
+ jsonWriter.name("w").value(key.mWidth);
+ jsonWriter.name("h").value(key.mHeight);
+ jsonWriter.endObject();
+ }
+
+ /* package */ static void writeJson(final SuggestedWords words, final JsonWriter jsonWriter)
+ throws IOException {
+ jsonWriter.beginObject();
+ jsonWriter.name("typedWordValid").value(words.mTypedWordValid);
+ jsonWriter.name("willAutoCorrect")
+ .value(words.mWillAutoCorrect);
+ jsonWriter.name("isPunctuationSuggestions")
+ .value(words.mIsPunctuationSuggestions);
+ jsonWriter.name("isObsoleteSuggestions").value(words.mIsObsoleteSuggestions);
+ jsonWriter.name("isPrediction").value(words.mIsPrediction);
+ jsonWriter.name("words");
+ jsonWriter.beginArray();
+ final int size = words.size();
+ for (int j = 0; j < size; j++) {
+ final SuggestedWordInfo wordInfo = words.getWordInfo(j);
+ jsonWriter.value(wordInfo.toString());
+ }
+ jsonWriter.endArray();
+ jsonWriter.endObject();
+ }
+}
diff --git a/java/src/com/android/inputmethod/research/LogUnit.java b/java/src/com/android/inputmethod/research/LogUnit.java
index ab9d2f857..884ade06b 100644
--- a/java/src/com/android/inputmethod/research/LogUnit.java
+++ b/java/src/com/android/inputmethod/research/LogUnit.java
@@ -16,10 +16,21 @@
package com.android.inputmethod.research;
+import android.content.SharedPreferences;
+import android.util.JsonWriter;
+import android.util.Log;
+import android.view.inputmethod.CompletionInfo;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.define.ProductionFlag;
import com.android.inputmethod.research.ResearchLogger.LogStatement;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
/**
* A group of log statements related to each other.
@@ -36,6 +47,8 @@ import java.util.List;
* been published recently, or whether the LogUnit contains numbers, etc.
*/
/* package */ class LogUnit {
+ private static final String TAG = LogUnit.class.getSimpleName();
+ private static final boolean DEBUG = false && ProductionFlag.IS_EXPERIMENTAL_DEBUG;
private final ArrayList<LogStatement> mLogStatementList;
private final ArrayList<Object[]> mValuesList;
// Assume that mTimeList is sorted in increasing order. Do not insert null values into
@@ -77,8 +90,13 @@ import java.util.List;
mTimeList.add(time);
}
- public void publishTo(final ResearchLog researchLog, final boolean isIncludingPrivateData) {
+ /**
+ * Publish the contents of this LogUnit to researchLog.
+ */
+ public synchronized void publishTo(final ResearchLog researchLog,
+ final boolean isIncludingPrivateData) {
final int size = mLogStatementList.size();
+ // Write out any logStatement that passes the privacy filter.
for (int i = 0; i < size; i++) {
final LogStatement logStatement = mLogStatementList.get(i);
if (!isIncludingPrivateData && logStatement.mIsPotentiallyPrivate) {
@@ -87,8 +105,70 @@ import java.util.List;
if (mIsPartOfMegaword && logStatement.mIsPotentiallyRevealing) {
continue;
}
- researchLog.outputEvent(mLogStatementList.get(i), mValuesList.get(i), mTimeList.get(i));
+ // Only retrieve the jsonWriter if we need to. If we don't get this far, then
+ // researchLog.getValidJsonWriter() will not open the file for writing.
+ final JsonWriter jsonWriter = researchLog.getValidJsonWriterLocked();
+ outputLogStatementToLocked(jsonWriter, mLogStatementList.get(i), mValuesList.get(i),
+ mTimeList.get(i));
+ }
+ }
+
+ private static final String CURRENT_TIME_KEY = "_ct";
+ private static final String UPTIME_KEY = "_ut";
+ private static final String EVENT_TYPE_KEY = "_ty";
+
+ /**
+ * Write the logStatement and its contents out through jsonWriter.
+ *
+ * Note that this method is not thread safe for the same jsonWriter. Callers must ensure
+ * thread safety.
+ */
+ private boolean outputLogStatementToLocked(final JsonWriter jsonWriter,
+ final LogStatement logStatement, final Object[] values, final Long time) {
+ if (DEBUG) {
+ if (logStatement.mKeys.length != values.length) {
+ Log.d(TAG, "Key and Value list sizes do not match. " + logStatement.mName);
+ }
+ }
+ try {
+ jsonWriter.beginObject();
+ jsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis());
+ jsonWriter.name(UPTIME_KEY).value(time);
+ jsonWriter.name(EVENT_TYPE_KEY).value(logStatement.mName);
+ final String[] keys = logStatement.mKeys;
+ final int length = values.length;
+ for (int i = 0; i < length; i++) {
+ jsonWriter.name(keys[i]);
+ final Object value = values[i];
+ if (value instanceof CharSequence) {
+ jsonWriter.value(value.toString());
+ } else if (value instanceof Number) {
+ jsonWriter.value((Number) value);
+ } else if (value instanceof Boolean) {
+ jsonWriter.value((Boolean) value);
+ } else if (value instanceof CompletionInfo[]) {
+ JsonUtils.writeJson((CompletionInfo[]) value, jsonWriter);
+ } else if (value instanceof SharedPreferences) {
+ JsonUtils.writeJson((SharedPreferences) value, jsonWriter);
+ } else if (value instanceof Key[]) {
+ JsonUtils.writeJson((Key[]) value, jsonWriter);
+ } else if (value instanceof SuggestedWords) {
+ JsonUtils.writeJson((SuggestedWords) value, jsonWriter);
+ } else if (value == null) {
+ jsonWriter.nullValue();
+ } else {
+ Log.w(TAG, "Unrecognized type to be logged: " +
+ (value == null ? "<null>" : value.getClass().getName()));
+ jsonWriter.nullValue();
+ }
+ }
+ jsonWriter.endObject();
+ } catch (IOException e) {
+ e.printStackTrace();
+ Log.w(TAG, "Error in JsonWriter; skipping LogStatement");
+ return false;
}
+ return true;
}
public void setWord(String word) {
diff --git a/java/src/com/android/inputmethod/research/ResearchLog.java b/java/src/com/android/inputmethod/research/ResearchLog.java
index 3c8731995..a6b1b889f 100644
--- a/java/src/com/android/inputmethod/research/ResearchLog.java
+++ b/java/src/com/android/inputmethod/research/ResearchLog.java
@@ -16,17 +16,10 @@
package com.android.inputmethod.research;
-import android.content.SharedPreferences;
-import android.os.SystemClock;
import android.util.JsonWriter;
import android.util.Log;
-import android.view.inputmethod.CompletionInfo;
-import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.latin.SuggestedWords;
-import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.define.ProductionFlag;
-import com.android.inputmethod.research.ResearchLogger.LogStatement;
import java.io.BufferedWriter;
import java.io.File;
@@ -34,7 +27,6 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
-import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
@@ -204,103 +196,17 @@ public class ResearchLog {
}
}
- private static final String CURRENT_TIME_KEY = "_ct";
- private static final String UPTIME_KEY = "_ut";
- private static final String EVENT_TYPE_KEY = "_ty";
-
- void outputEvent(final LogStatement logStatement, final Object[] values, final long time) {
- // Not thread safe.
- if (DEBUG) {
- if (logStatement.mKeys.length != values.length) {
- Log.d(TAG, "Key and Value list sizes do not match. " + logStatement.mName);
- }
- }
+ /**
+ * Return a JsonWriter for this ResearchLog. It is initialized the first time this method is
+ * called. The cached value is returned in future calls.
+ */
+ public JsonWriter getValidJsonWriterLocked() {
try {
if (mJsonWriter == NULL_JSON_WRITER) {
mJsonWriter = new JsonWriter(new BufferedWriter(new FileWriter(mFile)));
mJsonWriter.beginArray();
mHasWrittenData = true;
}
- mJsonWriter.beginObject();
- mJsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis());
- mJsonWriter.name(UPTIME_KEY).value(time);
- mJsonWriter.name(EVENT_TYPE_KEY).value(logStatement.mName);
- final String[] keys = logStatement.mKeys;
- final int length = values.length;
- for (int i = 0; i < length; i++) {
- mJsonWriter.name(keys[i]);
- Object value = values[i];
- if (value instanceof CharSequence) {
- mJsonWriter.value(value.toString());
- } 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<String,?> 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.getAltCode());
- 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();
- }
- mJsonWriter.endArray();
- } else if (value instanceof SuggestedWords) {
- SuggestedWords words = (SuggestedWords) value;
- mJsonWriter.beginObject();
- mJsonWriter.name("typedWordValid").value(words.mTypedWordValid);
- mJsonWriter.name("willAutoCorrect").value(words.mWillAutoCorrect);
- mJsonWriter.name("isPunctuationSuggestions")
- .value(words.mIsPunctuationSuggestions);
- 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 ? "<null>" : value.getClass().getName()));
- mJsonWriter.nullValue();
- }
- }
- mJsonWriter.endObject();
} catch (IOException e) {
e.printStackTrace();
Log.w(TAG, "Error in JsonWriter; disabling logging");
@@ -315,5 +221,6 @@ public class ResearchLog {
mJsonWriter = NULL_JSON_WRITER;
}
}
+ return mJsonWriter;
}
}