diff --git a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
index 2df7e5cf52fe23729c9f0bbf9b292ceb068febcd..6bc6acc0fc8cbf7de0b8c7d8b800905cec99def8 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
@@ -34,175 +34,197 @@ public final class PointerTrackerQueue {
     }
 
     private static final int INITIAL_CAPACITY = 10;
+    // Note: {@link #mExpandableArrayOfActivePointers} and {@link #mArraySize} are synchronized by
+    // {@link #mExpandableArrayOfActivePointers}
     private final ArrayList<Element> mExpandableArrayOfActivePointers =
             CollectionUtils.newArrayList(INITIAL_CAPACITY);
     private int mArraySize = 0;
 
-    public synchronized int size() {
-        return mArraySize;
+    public int size() {
+        synchronized (mExpandableArrayOfActivePointers) {
+            return mArraySize;
+        }
     }
 
-    public synchronized void add(final Element pointer) {
-        final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
-        final int arraySize = mArraySize;
-        if (arraySize < expandableArray.size()) {
-            expandableArray.set(arraySize, pointer);
-        } else {
-            expandableArray.add(pointer);
+    public void add(final Element pointer) {
+        synchronized (mExpandableArrayOfActivePointers) {
+            final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
+            final int arraySize = mArraySize;
+            if (arraySize < expandableArray.size()) {
+                expandableArray.set(arraySize, pointer);
+            } else {
+                expandableArray.add(pointer);
+            }
+            mArraySize = arraySize + 1;
         }
-        mArraySize = arraySize + 1;
     }
 
-    public synchronized void remove(final Element pointer) {
-        final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
-        final int arraySize = mArraySize;
-        int newSize = 0;
-        for (int index = 0; index < arraySize; index++) {
-            final Element element = expandableArray.get(index);
-            if (element == pointer) {
+    public void remove(final Element pointer) {
+        synchronized (mExpandableArrayOfActivePointers) {
+            final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
+            final int arraySize = mArraySize;
+            int newSize = 0;
+            for (int index = 0; index < arraySize; index++) {
+                final Element element = expandableArray.get(index);
+                if (element == pointer) {
+                    if (newSize != index) {
+                        Log.w(TAG, "Found duplicated element in remove: " + pointer);
+                    }
+                    continue; // Remove this element from the expandableArray.
+                }
                 if (newSize != index) {
-                    Log.w(TAG, "Found duplicated element in remove: " + pointer);
+                    // Shift this element toward the beginning of the expandableArray.
+                    expandableArray.set(newSize, element);
                 }
-                continue; // Remove this element from the expandableArray.
-            }
-            if (newSize != index) {
-                // Shift this element toward the beginning of the expandableArray.
-                expandableArray.set(newSize, element);
+                newSize++;
             }
-            newSize++;
+            mArraySize = newSize;
         }
-        mArraySize = newSize;
     }
 
-    public synchronized Element getOldestElement() {
-        return (mArraySize == 0) ? null : mExpandableArrayOfActivePointers.get(0);
+    public Element getOldestElement() {
+        synchronized (mExpandableArrayOfActivePointers) {
+            return (mArraySize == 0) ? null : mExpandableArrayOfActivePointers.get(0);
+        }
     }
 
-    public synchronized void releaseAllPointersOlderThan(final Element pointer,
-            final long eventTime) {
-        if (DEBUG) {
-            Log.d(TAG, "releaseAllPoniterOlderThan: " + pointer + " " + this);
-        }
-        final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
-        final int arraySize = mArraySize;
-        int newSize, index;
-        for (newSize = index = 0; index < arraySize; index++) {
-            final Element element = expandableArray.get(index);
-            if (element == pointer) {
-                break; // Stop releasing elements.
-            }
-            if (!element.isModifier()) {
-                element.onPhantomUpEvent(eventTime);
-                continue; // Remove this element from the expandableArray.
+    public void releaseAllPointersOlderThan(final Element pointer, final long eventTime) {
+        synchronized (mExpandableArrayOfActivePointers) {
+            if (DEBUG) {
+                Log.d(TAG, "releaseAllPoniterOlderThan: " + pointer + " " + this);
             }
-            if (newSize != index) {
-                // Shift this element toward the beginning of the expandableArray.
-                expandableArray.set(newSize, element);
-            }
-            newSize++;
-        }
-        // Shift rest of the expandableArray.
-        int count = 0;
-        for (; index < arraySize; index++) {
-            final Element element = expandableArray.get(index);
-            if (element == pointer) {
-                if (count > 0) {
-                    Log.w(TAG, "Found duplicated element in releaseAllPointersOlderThan: "
-                            + pointer);
+            final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
+            final int arraySize = mArraySize;
+            int newSize, index;
+            for (newSize = index = 0; index < arraySize; index++) {
+                final Element element = expandableArray.get(index);
+                if (element == pointer) {
+                    break; // Stop releasing elements.
+                }
+                if (!element.isModifier()) {
+                    element.onPhantomUpEvent(eventTime);
+                    continue; // Remove this element from the expandableArray.
+                }
+                if (newSize != index) {
+                    // Shift this element toward the beginning of the expandableArray.
+                    expandableArray.set(newSize, element);
                 }
-                count++;
-            }
-            if (newSize != index) {
-                expandableArray.set(newSize, expandableArray.get(index));
                 newSize++;
             }
+            // Shift rest of the expandableArray.
+            int count = 0;
+            for (; index < arraySize; index++) {
+                final Element element = expandableArray.get(index);
+                if (element == pointer) {
+                    if (count > 0) {
+                        Log.w(TAG, "Found duplicated element in releaseAllPointersOlderThan: "
+                                + pointer);
+                    }
+                    count++;
+                }
+                if (newSize != index) {
+                    expandableArray.set(newSize, expandableArray.get(index));
+                    newSize++;
+                }
+            }
+            mArraySize = newSize;
         }
-        mArraySize = newSize;
     }
 
     public void releaseAllPointers(final long eventTime) {
         releaseAllPointersExcept(null, eventTime);
     }
 
-    public synchronized void releaseAllPointersExcept(final Element pointer,
-            final long eventTime) {
-        if (DEBUG) {
-            if (pointer == null) {
-                Log.d(TAG, "releaseAllPoniters: " + this);
-            } else {
-                Log.d(TAG, "releaseAllPoniterExcept: " + pointer + " " + this);
-            }
-        }
-        final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
-        final int arraySize = mArraySize;
-        int newSize = 0, count = 0;
-        for (int index = 0; index < arraySize; index++) {
-            final Element element = expandableArray.get(index);
-            if (element == pointer) {
-                if (count > 0) {
-                    Log.w(TAG, "Found duplicated element in releaseAllPointersExcept: " + pointer);
+    public void releaseAllPointersExcept(final Element pointer, final long eventTime) {
+        synchronized (mExpandableArrayOfActivePointers) {
+            if (DEBUG) {
+                if (pointer == null) {
+                    Log.d(TAG, "releaseAllPoniters: " + this);
+                } else {
+                    Log.d(TAG, "releaseAllPoniterExcept: " + pointer + " " + this);
                 }
-                count++;
-            } else {
-                element.onPhantomUpEvent(eventTime);
-                continue; // Remove this element from the expandableArray.
             }
-            if (newSize != index) {
-                // Shift this element toward the beginning of the expandableArray.
-                expandableArray.set(newSize, element);
+            final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
+            final int arraySize = mArraySize;
+            int newSize = 0, count = 0;
+            for (int index = 0; index < arraySize; index++) {
+                final Element element = expandableArray.get(index);
+                if (element == pointer) {
+                    if (count > 0) {
+                        Log.w(TAG, "Found duplicated element in releaseAllPointersExcept: "
+                                + pointer);
+                    }
+                    count++;
+                } else {
+                    element.onPhantomUpEvent(eventTime);
+                    continue; // Remove this element from the expandableArray.
+                }
+                if (newSize != index) {
+                    // Shift this element toward the beginning of the expandableArray.
+                    expandableArray.set(newSize, element);
+                }
+                newSize++;
             }
-            newSize++;
+            mArraySize = newSize;
         }
-        mArraySize = newSize;
     }
 
-    public synchronized boolean hasModifierKeyOlderThan(final Element pointer) {
-        final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
-        final int arraySize = mArraySize;
-        for (int index = 0; index < arraySize; index++) {
-            final Element element = expandableArray.get(index);
-            if (element == pointer) {
-                return false; // Stop searching modifier key.
-            }
-            if (element.isModifier()) {
-                return true;
+    public boolean hasModifierKeyOlderThan(final Element pointer) {
+        synchronized (mExpandableArrayOfActivePointers) {
+            final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
+            final int arraySize = mArraySize;
+            for (int index = 0; index < arraySize; index++) {
+                final Element element = expandableArray.get(index);
+                if (element == pointer) {
+                    return false; // Stop searching modifier key.
+                }
+                if (element.isModifier()) {
+                    return true;
+                }
             }
+            return false;
         }
-        return false;
     }
 
-    public synchronized boolean isAnyInSlidingKeyInput() {
-        final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
-        final int arraySize = mArraySize;
-        for (int index = 0; index < arraySize; index++) {
-            final Element element = expandableArray.get(index);
-            if (element.isInSlidingKeyInput()) {
-                return true;
+    public boolean isAnyInSlidingKeyInput() {
+        synchronized (mExpandableArrayOfActivePointers) {
+            final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
+            final int arraySize = mArraySize;
+            for (int index = 0; index < arraySize; index++) {
+                final Element element = expandableArray.get(index);
+                if (element.isInSlidingKeyInput()) {
+                    return true;
+                }
             }
+            return false;
         }
-        return false;
     }
 
-    public synchronized void cancelAllPointerTracker() {
-        final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
-        final int arraySize = mArraySize;
-        for (int index = 0; index < arraySize; index++) {
-            final Element element = expandableArray.get(index);
-            element.cancelTracking();
+    public void cancelAllPointerTracker() {
+        synchronized (mExpandableArrayOfActivePointers) {
+            final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
+            final int arraySize = mArraySize;
+            for (int index = 0; index < arraySize; index++) {
+                final Element element = expandableArray.get(index);
+                element.cancelTracking();
+            }
         }
     }
 
     @Override
-    public synchronized String toString() {
-        final StringBuilder sb = new StringBuilder();
-        final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
-        final int arraySize = mArraySize;
-        for (int index = 0; index < arraySize; index++) {
-            final Element element = expandableArray.get(index);
-            if (sb.length() > 0)
-                sb.append(" ");
-            sb.append(element.toString());
+    public String toString() {
+        synchronized (mExpandableArrayOfActivePointers) {
+            final StringBuilder sb = new StringBuilder();
+            final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
+            final int arraySize = mArraySize;
+            for (int index = 0; index < arraySize; index++) {
+                final Element element = expandableArray.get(index);
+                if (sb.length() > 0) {
+                    sb.append(" ");
+                }
+                sb.append(element.toString());
+            }
+            return "[" + sb.toString() + "]";
         }
-        return "[" + sb.toString() + "]";
     }
 }