diff --git a/java/src/com/android/inputmethod/latin/InputPointers.java b/java/src/com/android/inputmethod/latin/InputPointers.java
index 2e638aaf3fd44d74db1207f537f943ca9fbca26b..6b489da307ad7e11e853813885695f379b58b106 100644
--- a/java/src/com/android/inputmethod/latin/InputPointers.java
+++ b/java/src/com/android/inputmethod/latin/InputPointers.java
@@ -16,14 +16,16 @@
 
 package com.android.inputmethod.latin;
 
+import android.util.Log;
+
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.utils.ResizableIntArray;
 
-import android.util.Log;
-
 // TODO: This class is not thread-safe.
 public final class InputPointers {
     private static final String TAG = InputPointers.class.getSimpleName();
+    private static final boolean DEBUG_TIME = false;
+
     private final int mDefaultCapacity;
     private final ResizableIntArray mXCoordinates;
     private final ResizableIntArray mYCoordinates;
@@ -38,10 +40,29 @@ public final class InputPointers {
         mTimes = new ResizableIntArray(defaultCapacity);
     }
 
+    private void fillWithLastTimeUntil(final int index) {
+        final int fromIndex = mTimes.getLength();
+        // Fill the gap with the latest time.
+        // See {@link #getTime(int)} and {@link #isValidTimeStamps()}.
+        if (fromIndex <= 0) {
+            return;
+        }
+        final int fillLength = index - fromIndex + 1;
+        if (fillLength <= 0) {
+            return;
+        }
+        final int lastTime = mTimes.get(fromIndex - 1);
+        mTimes.fill(lastTime, fromIndex, fillLength);
+    }
+
+    // TODO: Rename this method to addPointerAt
     public void addPointer(int index, int x, int y, int pointerId, int time) {
         mXCoordinates.add(index, x);
         mYCoordinates.add(index, y);
         mPointerIds.add(index, pointerId);
+        if (LatinImeLogger.sDBG || DEBUG_TIME) {
+            fillWithLastTimeUntil(index);
+        }
         mTimes.add(index, time);
     }
 
@@ -67,23 +88,6 @@ public final class InputPointers {
         mTimes.copy(ip.mTimes);
     }
 
-    /**
-     * Append the pointers in the specified {@link InputPointers} to the end of this.
-     * @param src the source {@link InputPointers} to read the data from.
-     * @param startPos the starting index of the pointers in {@code src}.
-     * @param length the number of pointers to be appended.
-     */
-    @UsedForTesting
-    void append(InputPointers src, int startPos, int length) {
-        if (length == 0) {
-            return;
-        }
-        mXCoordinates.append(src.mXCoordinates, startPos, length);
-        mYCoordinates.append(src.mYCoordinates, startPos, length);
-        mPointerIds.append(src.mPointerIds, startPos, length);
-        mTimes.append(src.mTimes, startPos, length);
-    }
-
     /**
      * Append the times, x-coordinates and y-coordinates in the specified {@link ResizableIntArray}
      * to the end of this.
@@ -141,7 +145,7 @@ public final class InputPointers {
     }
 
     public int[] getTimes() {
-        if (LatinImeLogger.sDBG) {
+        if (LatinImeLogger.sDBG || DEBUG_TIME) {
             if (!isValidTimeStamps()) {
                 throw new RuntimeException("Time stamps are invalid.");
             }
@@ -157,10 +161,11 @@ public final class InputPointers {
 
     private boolean isValidTimeStamps() {
         final int[] times = mTimes.getPrimitiveArray();
-        for (int i = 1; i < getPointerSize(); ++i) {
+        final int size = getPointerSize();
+        for (int i = 1; i < size; ++i) {
             if (times[i] < times[i - 1]) {
                 // dump
-                for (int j = 0; j < times.length; ++j) {
+                for (int j = 0; j < size; ++j) {
                     Log.d(TAG, "--- (" + j + ") " + times[j]);
                 }
                 return false;
diff --git a/tests/src/com/android/inputmethod/latin/InputPointersTests.java b/tests/src/com/android/inputmethod/latin/InputPointersTests.java
index 5095f9606a3c1d19caf50f4f4cffb66a6bd7a999..4c67d19275d926614eb1759ea334ca016e5d0917 100644
--- a/tests/src/com/android/inputmethod/latin/InputPointersTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputPointersTests.java
@@ -55,14 +55,22 @@ public class InputPointersTests extends AndroidTestCase {
         final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
         final int limit = src.getXCoordinates().length * 2 + 10;
         for (int i = 0; i < limit; i++) {
-            src.addPointer(i, i * 2, i * 3, i * 4);
+            final int x = i;
+            final int y = i * 2;
+            final int pointerId = i * 3;
+            final int time = i * 4;
+            src.addPointer(x, y, pointerId, time);
             assertEquals("size after add " + i, i + 1, src.getPointerSize());
         }
         for (int i = 0; i < limit; i++) {
-            assertEquals("xCoordinates at " + i, i, src.getXCoordinates()[i]);
-            assertEquals("yCoordinates at " + i, i * 2, src.getYCoordinates()[i]);
-            assertEquals("pointerIds at " + i, i * 3, src.getPointerIds()[i]);
-            assertEquals("times at " + i, i * 4, src.getTimes()[i]);
+            final int x = i;
+            final int y = i * 2;
+            final int pointerId = i * 3;
+            final int time = i * 4;
+            assertEquals("xCoordinates at " + i, x, src.getXCoordinates()[i]);
+            assertEquals("yCoordinates at " + i, y, src.getYCoordinates()[i]);
+            assertEquals("pointerIds at " + i, pointerId, src.getPointerIds()[i]);
+            assertEquals("times at " + i, time, src.getTimes()[i]);
         }
     }
 
@@ -70,14 +78,22 @@ public class InputPointersTests extends AndroidTestCase {
         final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
         final int limit = 1000, step = 100;
         for (int i = 0; i < limit; i += step) {
-            src.addPointer(i, i, i * 2, i * 3, i * 4);
+            final int x = i;
+            final int y = i * 2;
+            final int pointerId = i * 3;
+            final int time = i * 4;
+            src.addPointer(i, x, y, pointerId, time);
             assertEquals("size after add at " + i, i + 1, src.getPointerSize());
         }
         for (int i = 0; i < limit; i += step) {
-            assertEquals("xCoordinates at " + i, i, src.getXCoordinates()[i]);
-            assertEquals("yCoordinates at " + i, i * 2, src.getYCoordinates()[i]);
-            assertEquals("pointerIds at " + i, i * 3, src.getPointerIds()[i]);
-            assertEquals("times at " + i, i * 4, src.getTimes()[i]);
+            final int x = i;
+            final int y = i * 2;
+            final int pointerId = i * 3;
+            final int time = i * 4;
+            assertEquals("xCoordinates at " + i, x, src.getXCoordinates()[i]);
+            assertEquals("yCoordinates at " + i, y, src.getYCoordinates()[i]);
+            assertEquals("pointerIds at " + i, pointerId, src.getPointerIds()[i]);
+            assertEquals("times at " + i, time, src.getTimes()[i]);
         }
     }
 
@@ -85,7 +101,11 @@ public class InputPointersTests extends AndroidTestCase {
         final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
         final int limit = src.getXCoordinates().length * 2 + 10;
         for (int i = 0; i < limit; i++) {
-            src.addPointer(i, i * 2, i * 3, i * 4);
+            final int x = i;
+            final int y = i * 2;
+            final int pointerId = i * 3;
+            final int time = i * 4;
+            src.addPointer(x, y, pointerId, time);
         }
         final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
         dst.set(src);
@@ -100,7 +120,11 @@ public class InputPointersTests extends AndroidTestCase {
         final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
         final int limit = 100;
         for (int i = 0; i < limit; i++) {
-            src.addPointer(i, i * 2, i * 3, i * 4);
+            final int x = i;
+            final int y = i * 2;
+            final int pointerId = i * 3;
+            final int time = i * 4;
+            src.addPointer(x, y, pointerId, time);
         }
         final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
         dst.copy(src);
@@ -121,106 +145,135 @@ public class InputPointersTests extends AndroidTestCase {
     }
 
     public void testAppend() {
-        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
-        final int srcLen = 100;
-        for (int i = 0; i < srcLen; i++) {
-            src.addPointer(i, i * 2, i * 3, i * 4);
-        }
-        final int dstLen = 50;
+        final int dstLength = 50;
         final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
-        for (int i = 0; i < dstLen; i++) {
-            final int value = -i - 1;
-            dst.addPointer(value * 4, value * 3, value * 2, value);
+        for (int i = 0; i < dstLength; i++) {
+            final int x = i * 4;
+            final int y = i * 3;
+            final int pointerId = i * 2;
+            final int time = i;
+            dst.addPointer(x, y, pointerId, time);
         }
         final InputPointers dstCopy = new InputPointers(DEFAULT_CAPACITY);
         dstCopy.copy(dst);
 
-        dst.append(src, 0, 0);
-        assertEquals("size after append zero", dstLen, dst.getPointerSize());
+        final ResizableIntArray srcXCoords = new ResizableIntArray(DEFAULT_CAPACITY);
+        final ResizableIntArray srcYCoords = new ResizableIntArray(DEFAULT_CAPACITY);
+        final ResizableIntArray srcPointerIds = new ResizableIntArray(DEFAULT_CAPACITY);
+        final ResizableIntArray srcTimes = new ResizableIntArray(DEFAULT_CAPACITY);
+        final int srcLength = 100;
+        final int srcPointerId = 10;
+        for (int i = 0; i < srcLength; i++) {
+            final int x = i;
+            final int y = i * 2;
+            // The time value must be larger than <code>dst</code>.
+            final int time = i * 4 + dstLength;
+            srcXCoords.add(x);
+            srcYCoords.add(y);
+            srcPointerIds.add(srcPointerId);
+            srcTimes.add(time);
+        }
+
+        final int startPos = 0;
+        dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords,
+                startPos, 0 /* length */);
+        assertEquals("size after append zero", dstLength, dst.getPointerSize());
         assertIntArrayEquals("xCoordinates after append zero",
-                dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLen);
+                dstCopy.getXCoordinates(), startPos, dst.getXCoordinates(), startPos, dstLength);
         assertIntArrayEquals("yCoordinates after append zero",
-                dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLen);
+                dstCopy.getYCoordinates(), startPos, dst.getYCoordinates(), startPos, dstLength);
         assertIntArrayEquals("pointerIds after append zero",
-                dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLen);
+                dstCopy.getPointerIds(), startPos, dst.getPointerIds(), startPos, dstLength);
         assertIntArrayEquals("times after append zero",
-                dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLen);
+                dstCopy.getTimes(), startPos, dst.getTimes(), startPos, dstLength);
 
-        dst.append(src, 0, srcLen);
-        assertEquals("size after append", dstLen + srcLen, dst.getPointerSize());
+        dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords,
+                startPos, srcLength);
+        assertEquals("size after append", dstLength + srcLength, dst.getPointerSize());
         assertTrue("primitive length after append",
-                dst.getPointerIds().length >= dstLen + srcLen);
+                dst.getPointerIds().length >= dstLength + srcLength);
         assertIntArrayEquals("original xCoordinates values after append",
-                dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLen);
+                dstCopy.getXCoordinates(), startPos, dst.getXCoordinates(), startPos, dstLength);
         assertIntArrayEquals("original yCoordinates values after append",
-                dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLen);
+                dstCopy.getYCoordinates(), startPos, dst.getYCoordinates(), startPos, dstLength);
         assertIntArrayEquals("original pointerIds values after append",
-                dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLen);
+                dstCopy.getPointerIds(), startPos, dst.getPointerIds(), startPos, dstLength);
         assertIntArrayEquals("original times values after append",
-                dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLen);
+                dstCopy.getTimes(), startPos, dst.getTimes(), startPos, dstLength);
         assertIntArrayEquals("appended xCoordinates values after append",
-                src.getXCoordinates(), 0, dst.getXCoordinates(), dstLen, srcLen);
+                srcXCoords.getPrimitiveArray(), startPos, dst.getXCoordinates(),
+                dstLength, srcLength);
         assertIntArrayEquals("appended yCoordinates values after append",
-                src.getYCoordinates(), 0, dst.getYCoordinates(), dstLen, srcLen);
+                srcYCoords.getPrimitiveArray(), startPos, dst.getYCoordinates(),
+                dstLength, srcLength);
         assertIntArrayEquals("appended pointerIds values after append",
-                src.getPointerIds(), 0, dst.getPointerIds(), dstLen, srcLen);
+                srcPointerIds.getPrimitiveArray(), startPos, dst.getPointerIds(),
+                dstLength, srcLength);
         assertIntArrayEquals("appended times values after append",
-                src.getTimes(), 0, dst.getTimes(), dstLen, srcLen);
+                srcTimes.getPrimitiveArray(), startPos, dst.getTimes(), dstLength, srcLength);
     }
 
     public void testAppendResizableIntArray() {
-        final int srcLen = 100;
+        final int dstLength = 50;
+        final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
+        for (int i = 0; i < dstLength; i++) {
+            final int x = i * 4;
+            final int y = i * 3;
+            final int pointerId = i * 2;
+            final int time = i;
+            dst.addPointer(x, y, pointerId, time);
+        }
+        final InputPointers dstCopy = new InputPointers(DEFAULT_CAPACITY);
+        dstCopy.copy(dst);
+
+        final int srcLength = 100;
         final int srcPointerId = 1;
-        final int[] srcPointerIds = new int[srcLen];
+        final int[] srcPointerIds = new int[srcLength];
         Arrays.fill(srcPointerIds, srcPointerId);
         final ResizableIntArray srcTimes = new ResizableIntArray(DEFAULT_CAPACITY);
         final ResizableIntArray srcXCoords = new ResizableIntArray(DEFAULT_CAPACITY);
         final ResizableIntArray srcYCoords= new ResizableIntArray(DEFAULT_CAPACITY);
-        for (int i = 0; i < srcLen; i++) {
-            srcTimes.add(i * 2);
-            srcXCoords.add(i * 3);
-            srcYCoords.add(i * 4);
+        for (int i = 0; i < srcLength; i++) {
+            // The time value must be larger than <code>dst</code>.
+            final int time = i * 2 + dstLength;
+            final int x = i * 3;
+            final int y = i * 4;
+            srcTimes.add(time);
+            srcXCoords.add(x);
+            srcYCoords.add(y);
         }
-        final int dstLen = 50;
-        final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
-        for (int i = 0; i < dstLen; i++) {
-            final int value = -i - 1;
-            dst.addPointer(value * 4, value * 3, value * 2, value);
-        }
-        final InputPointers dstCopy = new InputPointers(DEFAULT_CAPACITY);
-        dstCopy.copy(dst);
 
         dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, 0, 0);
-        assertEquals("size after append zero", dstLen, dst.getPointerSize());
+        assertEquals("size after append zero", dstLength, dst.getPointerSize());
         assertIntArrayEquals("xCoordinates after append zero",
-                dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLen);
+                dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLength);
         assertIntArrayEquals("yCoordinates after append zero",
-                dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLen);
+                dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLength);
         assertIntArrayEquals("pointerIds after append zero",
-                dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLen);
+                dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLength);
         assertIntArrayEquals("times after append zero",
-                dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLen);
+                dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLength);
 
-        dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, 0, srcLen);
-        assertEquals("size after append", dstLen + srcLen, dst.getPointerSize());
+        dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, 0, srcLength);
+        assertEquals("size after append", dstLength + srcLength, dst.getPointerSize());
         assertTrue("primitive length after append",
-                dst.getPointerIds().length >= dstLen + srcLen);
+                dst.getPointerIds().length >= dstLength + srcLength);
         assertIntArrayEquals("original xCoordinates values after append",
-                dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLen);
+                dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLength);
         assertIntArrayEquals("original yCoordinates values after append",
-                dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLen);
+                dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLength);
         assertIntArrayEquals("original pointerIds values after append",
-                dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLen);
+                dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLength);
         assertIntArrayEquals("original times values after append",
-                dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLen);
+                dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLength);
         assertIntArrayEquals("appended xCoordinates values after append",
-                srcXCoords.getPrimitiveArray(), 0, dst.getXCoordinates(), dstLen, srcLen);
+                srcXCoords.getPrimitiveArray(), 0, dst.getXCoordinates(), dstLength, srcLength);
         assertIntArrayEquals("appended yCoordinates values after append",
-                srcYCoords.getPrimitiveArray(), 0, dst.getYCoordinates(), dstLen, srcLen);
+                srcYCoords.getPrimitiveArray(), 0, dst.getYCoordinates(), dstLength, srcLength);
         assertIntArrayEquals("appended pointerIds values after append",
-                srcPointerIds, 0, dst.getPointerIds(), dstLen, srcLen);
+                srcPointerIds, 0, dst.getPointerIds(), dstLength, srcLength);
         assertIntArrayEquals("appended times values after append",
-                srcTimes.getPrimitiveArray(), 0, dst.getTimes(), dstLen, srcLen);
+                srcTimes.getPrimitiveArray(), 0, dst.getTimes(), dstLength, srcLength);
     }
 
     // TODO: Consolidate this method with
@@ -250,14 +303,24 @@ public class InputPointersTests extends AndroidTestCase {
         final int limit = 100;
         final int shiftAmount = 20;
         for (int i = 0; i < limit; i++) {
-            src.addPointer(i, i * 2, i * 3, i * 4);
+            final int x = i;
+            final int y = i * 2;
+            final int pointerId = i * 3;
+            final int time = i * 4;
+            src.addPointer(x, y, pointerId, time);
         }
         src.shift(shiftAmount);
+        assertEquals("length after shift", src.getPointerSize(), limit - shiftAmount);
         for (int i = 0; i < limit - shiftAmount; ++i) {
-            assertEquals("xCoordinates at " + i, i + shiftAmount, src.getXCoordinates()[i]);
-            assertEquals("yCoordinates at " + i, (i + shiftAmount) * 2, src.getYCoordinates()[i]);
-            assertEquals("pointerIds at " + i, (i + shiftAmount) * 3, src.getPointerIds()[i]);
-            assertEquals("times at " + i, (i + shiftAmount) * 4, src.getTimes()[i]);
+            final int oldIndex = i + shiftAmount;
+            final int x = oldIndex;
+            final int y = oldIndex * 2;
+            final int pointerId = oldIndex * 3;
+            final int time = oldIndex * 4;
+            assertEquals("xCoordinates at " + i, x, src.getXCoordinates()[i]);
+            assertEquals("yCoordinates at " + i, y, src.getYCoordinates()[i]);
+            assertEquals("pointerIds at " + i, pointerId, src.getPointerIds()[i]);
+            assertEquals("times at " + i, time, src.getTimes()[i]);
         }
     }
 }