aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/research/ResearchLog.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/research/ResearchLog.java')
-rw-r--r--java/src/com/android/inputmethod/research/ResearchLog.java66
1 files changed, 47 insertions, 19 deletions
diff --git a/java/src/com/android/inputmethod/research/ResearchLog.java b/java/src/com/android/inputmethod/research/ResearchLog.java
index 9016e23b3..35a491f2c 100644
--- a/java/src/com/android/inputmethod/research/ResearchLog.java
+++ b/java/src/com/android/inputmethod/research/ResearchLog.java
@@ -20,11 +20,11 @@ import android.content.Context;
import android.util.JsonWriter;
import android.util.Log;
+import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.define.ProductionFlag;
import java.io.BufferedWriter;
import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
@@ -47,14 +47,15 @@ import java.util.concurrent.TimeUnit;
* 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}.
+ * This functionality is off by default. See
+ * {@link ProductionFlag#USES_DEVELOPMENT_ONLY_DIAGNOSTICS}.
*/
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 boolean DEBUG = false
+ && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
private static final long FLUSH_DELAY_IN_MS = 1000 * 5;
- private static final int ABORT_TIMEOUT_IN_MS = 1000 * 4;
/* package */ final ScheduledExecutorService mExecutor;
/* package */ final File mFile;
@@ -99,8 +100,10 @@ public class ResearchLog {
* output.
*
* See class comment for details about {@code JsonWriter} construction.
+ *
+ * @param onClosed run after the close() operation has completed asynchronously
*/
- public synchronized void close(final Runnable onClosed) {
+ private synchronized void close(final Runnable onClosed) {
mExecutor.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
@@ -117,6 +120,8 @@ public class ResearchLog {
} catch (Exception e) {
Log.d(TAG, "error when closing ResearchLog:", e);
} finally {
+ // Marking the file as read-only signals that this log file is ready to be
+ // uploaded.
if (mFile != null && mFile.exists()) {
mFile.setWritable(false, false);
}
@@ -131,15 +136,24 @@ public class ResearchLog {
mExecutor.shutdown();
}
- private boolean mIsAbortSuccessful;
+ /**
+ * Block until the research log has shut down and spooled out all output or {@code timeout}
+ * occurs.
+ *
+ * @param timeout time to wait for close in milliseconds
+ */
+ public void blockingClose(final long timeout) {
+ close(null);
+ awaitTermination(timeout, TimeUnit.MILLISECONDS);
+ }
/**
- * Waits for publication requests to finish, closes the {@link JsonWriter}, but then deletes the
- * backing file used for output.
+ * Waits for publication requests to finish, closes the JsonWriter, but then deletes the backing
+ * output file.
*
- * See class comment for details about {@code JsonWriter} construction.
+ * @param onAbort run after the abort() operation has completed asynchronously
*/
- public synchronized void abort() {
+ private synchronized void abort(final Runnable onAbort) {
mExecutor.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
@@ -151,7 +165,10 @@ public class ResearchLog {
}
} finally {
if (mFile != null) {
- mIsAbortSuccessful = mFile.delete();
+ mFile.delete();
+ }
+ if (onAbort != null) {
+ onAbort.run();
}
}
return null;
@@ -161,14 +178,25 @@ public class ResearchLog {
mExecutor.shutdown();
}
- public boolean blockingAbort() throws InterruptedException {
- abort();
- mExecutor.awaitTermination(ABORT_TIMEOUT_IN_MS, TimeUnit.MILLISECONDS);
- return mIsAbortSuccessful;
+ /**
+ * Block until the research log has aborted or {@code timeout} occurs.
+ *
+ * @param timeout time to wait for close in milliseconds
+ */
+ public void blockingAbort(final long timeout) {
+ abort(null);
+ awaitTermination(timeout, TimeUnit.MILLISECONDS);
}
- public void awaitTermination(int delay, TimeUnit timeUnit) throws InterruptedException {
- mExecutor.awaitTermination(delay, timeUnit);
+ @UsedForTesting
+ public void awaitTermination(final long delay, final TimeUnit timeUnit) {
+ try {
+ if (!mExecutor.awaitTermination(delay, timeUnit)) {
+ Log.e(TAG, "ResearchLog executor timed out while awaiting terminaion");
+ }
+ } catch (final InterruptedException e) {
+ Log.e(TAG, "ResearchLog executor interrupted while awaiting terminaion", e);
+ }
}
/* package */ synchronized void flush() {
@@ -214,10 +242,10 @@ public class ResearchLog {
return null;
}
});
- } catch (RejectedExecutionException e) {
+ } catch (final RejectedExecutionException e) {
// TODO: Add code to record loss of data, and report.
if (DEBUG) {
- Log.d(TAG, "ResearchLog.publish() rejecting scheduled execution");
+ Log.d(TAG, "ResearchLog.publish() rejecting scheduled execution", e);
}
}
}