diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 3b4bb191393e5a239a44ab43f35cbc222c6053d0..6fcac9a6573052ad1021be03b89dd92140134f65 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -2652,11 +2652,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         }
     }
 
-    // Used by the RingCharBuffer
-    public boolean isWordSeparator(final int code) {
-        return mSettings.getCurrent().isWordSeparator(code);
-    }
-
     // TODO: Make this private
     // Outside LatinIME, only used by the {@link InputTestsBase} test suite.
     @UsedForTesting
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 084d3308cb248d357e5a9d31dc4a164035b64181..adc92d02175c484c5f0c8d51e1991de8deca52b0 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -152,6 +152,10 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
         return mSettingsValues.mWordSeparators;
     }
 
+    public boolean isWordSeparator(final int code) {
+        return mSettingsValues.isWordSeparator(code);
+    }
+
     public Locale getCurrentLocale() {
         return mCurrentLocale;
     }
diff --git a/java/src/com/android/inputmethod/latin/utils/UserLogRingCharBuffer.java b/java/src/com/android/inputmethod/latin/utils/UserLogRingCharBuffer.java
new file mode 100644
index 0000000000000000000000000000000000000000..3e67e8216925b7734d5a45464ec37706b5e32e28
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/utils/UserLogRingCharBuffer.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2013 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.utils;
+
+import android.inputmethodservice.InputMethodService;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.latin.Settings;
+import com.android.inputmethod.latin.utils.Utils.UsabilityStudyLogUtils;
+
+public final class UserLogRingCharBuffer {
+    public /* for test */ static final int BUFSIZE = 20;
+    public /* for test */ int mLength = 0;
+
+    private static UserLogRingCharBuffer sUserLogRingCharBuffer = new UserLogRingCharBuffer();
+    private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC';
+    private static final int INVALID_COORDINATE = -2;
+    private boolean mEnabled = false;
+    private int mEnd = 0;
+    private char[] mCharBuf = new char[BUFSIZE];
+    private int[] mXBuf = new int[BUFSIZE];
+    private int[] mYBuf = new int[BUFSIZE];
+
+    private UserLogRingCharBuffer() {
+        // Intentional empty constructor for singleton.
+    }
+
+    @UsedForTesting
+    public static UserLogRingCharBuffer getInstance() {
+        return sUserLogRingCharBuffer;
+    }
+
+    public static UserLogRingCharBuffer init(final InputMethodService context,
+            final boolean enabled, final boolean usabilityStudy) {
+        if (!(enabled || usabilityStudy)) {
+            return null;
+        }
+        sUserLogRingCharBuffer.mEnabled = true;
+        UsabilityStudyLogUtils.getInstance().init(context);
+        return sUserLogRingCharBuffer;
+    }
+
+    private static int normalize(final int in) {
+        int ret = in % BUFSIZE;
+        return ret < 0 ? ret + BUFSIZE : ret;
+    }
+
+    // TODO: accept code points
+    @UsedForTesting
+    public void push(final char c, final int x, final int y) {
+        if (!mEnabled) {
+            return;
+        }
+        mCharBuf[mEnd] = c;
+        mXBuf[mEnd] = x;
+        mYBuf[mEnd] = y;
+        mEnd = normalize(mEnd + 1);
+        if (mLength < BUFSIZE) {
+            ++mLength;
+        }
+    }
+
+    public char pop() {
+        if (mLength < 1) {
+            return PLACEHOLDER_DELIMITER_CHAR;
+        }
+        mEnd = normalize(mEnd - 1);
+        --mLength;
+        return mCharBuf[mEnd];
+    }
+
+    public char getBackwardNthChar(final int n) {
+        if (mLength <= n || n < 0) {
+            return PLACEHOLDER_DELIMITER_CHAR;
+        }
+        return mCharBuf[normalize(mEnd - n - 1)];
+    }
+
+    public int getPreviousX(final char c, final int back) {
+        final int index = normalize(mEnd - 2 - back);
+        if (mLength <= back
+                || Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) {
+            return INVALID_COORDINATE;
+        }
+        return mXBuf[index];
+    }
+
+    public int getPreviousY(final char c, final int back) {
+        int index = normalize(mEnd - 2 - back);
+        if (mLength <= back
+                || Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) {
+            return INVALID_COORDINATE;
+        }
+        return mYBuf[index];
+    }
+
+    public String getLastWord(final int ignoreCharCount) {
+        final StringBuilder sb = new StringBuilder();
+        int i = ignoreCharCount;
+        for (; i < mLength; ++i) {
+            final char c = mCharBuf[normalize(mEnd - 1 - i)];
+            if (!Settings.getInstance().isWordSeparator(c)) {
+                break;
+            }
+        }
+        for (; i < mLength; ++i) {
+            char c = mCharBuf[normalize(mEnd - 1 - i)];
+            if (!Settings.getInstance().isWordSeparator(c)) {
+                sb.append(c);
+            } else {
+                break;
+            }
+        }
+        return sb.reverse().toString();
+    }
+
+    public void reset() {
+        mLength = 0;
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/utils/Utils.java b/java/src/com/android/inputmethod/latin/utils/Utils.java
index 8070a6ea4155afd978586144019b35914c750bb9..c4e18ed7e0bfa041dca15efa335a2dd74b5ad017 100644
--- a/java/src/com/android/inputmethod/latin/utils/Utils.java
+++ b/java/src/com/android/inputmethod/latin/utils/Utils.java
@@ -26,7 +26,6 @@ import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.inputmethodservice.InputMethodService;
 import android.net.Uri;
-import android.os.AsyncTask;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -34,9 +33,7 @@ import android.os.Process;
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.LatinIME;
 import com.android.inputmethod.latin.LatinImeLogger;
 import com.android.inputmethod.latin.SuggestedWords;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
@@ -63,121 +60,6 @@ public final class Utils {
         // This utility class is not publicly instantiable.
     }
 
-    // TODO: Make this an external class
-    public /* for test */ static final class RingCharBuffer {
-        public /* for test */ static final int BUFSIZE = 20;
-        public /* for test */ int mLength = 0;
-
-        private static RingCharBuffer sRingCharBuffer = new RingCharBuffer();
-        private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC';
-        private static final int INVALID_COORDINATE = -2;
-        private InputMethodService mContext;
-        private boolean mEnabled = false;
-        private int mEnd = 0;
-        private char[] mCharBuf = new char[BUFSIZE];
-        private int[] mXBuf = new int[BUFSIZE];
-        private int[] mYBuf = new int[BUFSIZE];
-
-        private RingCharBuffer() {
-            // Intentional empty constructor for singleton.
-        }
-
-        @UsedForTesting
-        public static RingCharBuffer getInstance() {
-            return sRingCharBuffer;
-        }
-
-        public static RingCharBuffer init(final InputMethodService context, final boolean enabled,
-                final boolean usabilityStudy) {
-            if (!(enabled || usabilityStudy)) {
-                return null;
-            }
-            sRingCharBuffer.mContext = context;
-            sRingCharBuffer.mEnabled = true;
-            UsabilityStudyLogUtils.getInstance().init(context);
-            return sRingCharBuffer;
-        }
-
-        private static int normalize(final int in) {
-            int ret = in % BUFSIZE;
-            return ret < 0 ? ret + BUFSIZE : ret;
-        }
-
-        // TODO: accept code points
-        @UsedForTesting
-        public void push(final char c, final int x, final int y) {
-            if (!mEnabled) {
-                return;
-            }
-            mCharBuf[mEnd] = c;
-            mXBuf[mEnd] = x;
-            mYBuf[mEnd] = y;
-            mEnd = normalize(mEnd + 1);
-            if (mLength < BUFSIZE) {
-                ++mLength;
-            }
-        }
-
-        public char pop() {
-            if (mLength < 1) {
-                return PLACEHOLDER_DELIMITER_CHAR;
-            }
-            mEnd = normalize(mEnd - 1);
-            --mLength;
-            return mCharBuf[mEnd];
-        }
-
-        public char getBackwardNthChar(final int n) {
-            if (mLength <= n || n < 0) {
-                return PLACEHOLDER_DELIMITER_CHAR;
-            }
-            return mCharBuf[normalize(mEnd - n - 1)];
-        }
-
-        public int getPreviousX(final char c, final int back) {
-            final int index = normalize(mEnd - 2 - back);
-            if (mLength <= back
-                    || Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) {
-                return INVALID_COORDINATE;
-            }
-            return mXBuf[index];
-        }
-
-        public int getPreviousY(final char c, final int back) {
-            int index = normalize(mEnd - 2 - back);
-            if (mLength <= back
-                    || Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) {
-                return INVALID_COORDINATE;
-            }
-            return mYBuf[index];
-        }
-
-        public String getLastWord(final int ignoreCharCount) {
-            final StringBuilder sb = new StringBuilder();
-            final LatinIME latinIme = (LatinIME)mContext;
-            int i = ignoreCharCount;
-            for (; i < mLength; ++i) {
-                final char c = mCharBuf[normalize(mEnd - 1 - i)];
-                if (!latinIme.isWordSeparator(c)) {
-                    break;
-                }
-            }
-            for (; i < mLength; ++i) {
-                char c = mCharBuf[normalize(mEnd - 1 - i)];
-                if (!latinIme.isWordSeparator(c)) {
-                    sb.append(c);
-                } else {
-                    break;
-                }
-            }
-            return sb.reverse().toString();
-        }
-
-        public void reset() {
-            mLength = 0;
-        }
-    }
-
     // TODO: Make this an external class
     public static final class UsabilityStudyLogUtils {
         // TODO: remove code duplication with ResearchLog class
@@ -395,7 +277,7 @@ public final class Utils {
     // TODO: Make this an external class
     public static final class Stats {
         public static void onNonSeparator(final char code, final int x, final int y) {
-            RingCharBuffer.getInstance().push(code, x, y);
+            UserLogRingCharBuffer.getInstance().push(code, x, y);
             LatinImeLogger.logOnInputChar();
         }
 
@@ -410,7 +292,7 @@ public final class Utils {
             for (int i = 0; i < length; i = Character.offsetByCodePoints(separator, i, 1)) {
                 int codePoint = Character.codePointAt(separator, i);
                 // TODO: accept code points
-                RingCharBuffer.getInstance().push((char)codePoint, x, y);
+                UserLogRingCharBuffer.getInstance().push((char)codePoint, x, y);
             }
             LatinImeLogger.logOnInputSeparator();
         }