diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index efb0d77eaf687a35d9f5a44d7bafe090d612b5ab..d50d096c6a54c4e5dc8f91624a2c77605c245434 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 41884d34a367fd31bdeae96b55f1f6ad0c044537..861c23b04ccbde9800570b396f81ec1f138da112 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 7072dda23cac786d5f68f936447abf853f732004..384ed79a87c4c0fc7440267c0521365d90c3ca37 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<String,?> entry : prefs.getAll().entrySet()) {
+                builder.append("\t" + entry.getKey());
+                Object value = entry.getValue();
+                builder.append("=" + ((value == null) ? "<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 838effe2caaeb7cefdc3b3e988fa7a8a51e9a11f..c73a931ea056f1e4d79962f715b469e2532093c7 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<LatinIME> {
         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<LatinIME> {
         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);