Merge "Add BatchInputArbiter"

This commit is contained in:
Tadashi G. Takaoka 2013-12-26 05:50:07 +00:00 committed by Android (Google) Code Review
commit 3fbcf48591
4 changed files with 269 additions and 107 deletions

View file

@ -22,12 +22,13 @@ import android.os.SystemClock;
import android.util.Log; import android.util.Log;
import android.view.MotionEvent; import android.view.MotionEvent;
import com.android.inputmethod.keyboard.internal.BatchInputArbiter;
import com.android.inputmethod.keyboard.internal.BatchInputArbiter.BatchInputArbiterListener;
import com.android.inputmethod.keyboard.internal.BogusMoveEventDetector; import com.android.inputmethod.keyboard.internal.BogusMoveEventDetector;
import com.android.inputmethod.keyboard.internal.GestureEnabler; import com.android.inputmethod.keyboard.internal.GestureEnabler;
import com.android.inputmethod.keyboard.internal.GestureStrokeDrawingParams; import com.android.inputmethod.keyboard.internal.GestureStrokeDrawingParams;
import com.android.inputmethod.keyboard.internal.GestureStrokeDrawingPoints; import com.android.inputmethod.keyboard.internal.GestureStrokeDrawingPoints;
import com.android.inputmethod.keyboard.internal.GestureStrokeRecognitionParams; import com.android.inputmethod.keyboard.internal.GestureStrokeRecognitionParams;
import com.android.inputmethod.keyboard.internal.GestureStrokeRecognitionPoints;
import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
import com.android.inputmethod.keyboard.internal.TypingTimeRecorder; import com.android.inputmethod.keyboard.internal.TypingTimeRecorder;
import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Constants;
@ -43,7 +44,8 @@ import com.android.inputmethod.research.ResearchLogger;
import java.util.ArrayList; import java.util.ArrayList;
public final class PointerTracker implements PointerTrackerQueue.Element { public final class PointerTracker implements PointerTrackerQueue.Element,
BatchInputArbiterListener {
private static final String TAG = PointerTracker.class.getSimpleName(); private static final String TAG = PointerTracker.class.getSimpleName();
private static final boolean DEBUG_EVENT = false; private static final boolean DEBUG_EVENT = false;
private static final boolean DEBUG_MOVE_EVENT = false; private static final boolean DEBUG_MOVE_EVENT = false;
@ -160,12 +162,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
private boolean mIsDetectingGesture = false; // per PointerTracker. private boolean mIsDetectingGesture = false; // per PointerTracker.
private static boolean sInGesture = false; private static boolean sInGesture = false;
private static long sGestureFirstDownTime;
private static TypingTimeRecorder sTypingTimeRecorder; private static TypingTimeRecorder sTypingTimeRecorder;
private static final InputPointers sAggregatedPointers = new InputPointers(
GestureStrokeRecognitionPoints.DEFAULT_CAPACITY);
private static int sLastRecognitionPointSize = 0; // synchronized using sAggregatedPointers
private static long sLastRecognitionTime = 0; // synchronized using sAggregatedPointers
// The position and time at which first down event occurred. // The position and time at which first down event occurred.
private long mDownTime; private long mDownTime;
@ -203,7 +200,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
// true if dragging finger is allowed. // true if dragging finger is allowed.
private boolean mIsAllowedDraggingFinger; private boolean mIsAllowedDraggingFinger;
private final GestureStrokeRecognitionPoints mGestureStrokeRecognitionPoints; private final BatchInputArbiter mBatchInputArbiter;
private final GestureStrokeDrawingPoints mGestureStrokeDrawingPoints; private final GestureStrokeDrawingPoints mGestureStrokeDrawingPoints;
// TODO: Add PointerTrackerFactory singleton and move some class static methods into it. // TODO: Add PointerTrackerFactory singleton and move some class static methods into it.
@ -287,8 +284,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
private PointerTracker(final int id) { private PointerTracker(final int id) {
mPointerId = id; mPointerId = id;
mGestureStrokeRecognitionPoints = new GestureStrokeRecognitionPoints( mBatchInputArbiter = new BatchInputArbiter(id, sGestureStrokeRecognitionParams);
id, sGestureStrokeRecognitionParams);
mGestureStrokeDrawingPoints = new GestureStrokeDrawingPoints(sGestureStrokeDrawingParams); mGestureStrokeDrawingPoints = new GestureStrokeDrawingPoints(sGestureStrokeDrawingParams);
} }
@ -410,7 +406,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
mKeyboardLayoutHasBeenChanged = true; mKeyboardLayoutHasBeenChanged = true;
final int keyWidth = mKeyboard.mMostCommonKeyWidth; final int keyWidth = mKeyboard.mMostCommonKeyWidth;
final int keyHeight = mKeyboard.mMostCommonKeyHeight; final int keyHeight = mKeyboard.mMostCommonKeyHeight;
mGestureStrokeRecognitionPoints.setKeyboardGeometry(keyWidth, mKeyboard.mOccupiedHeight); mBatchInputArbiter.setKeyboardGeometry(keyWidth, mKeyboard.mOccupiedHeight);
final Key newKey = mKeyDetector.detectHitKey(mKeyX, mKeyY); final Key newKey = mKeyDetector.detectHitKey(mKeyX, mKeyY);
if (newKey != mCurrentKey) { if (newKey != mCurrentKey) {
if (sDrawingProxy != null) { if (sDrawingProxy != null) {
@ -578,27 +574,16 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
return sPointerTrackerQueue.getOldestElement() == this; return sPointerTrackerQueue.getOldestElement() == this;
} }
/** // Implements {@link BatchInputArbiterListener}.
* Determines whether the batch input has started or not. @Override
* @return true if the batch input has started successfully. public void onStartBatchInput() {
*/
private boolean mayStartBatchInput() {
if (!mGestureStrokeRecognitionPoints.isStartOfAGesture()) {
return false;
}
if (DEBUG_LISTENER) { if (DEBUG_LISTENER) {
Log.d(TAG, String.format("[%d] onStartBatchInput", mPointerId)); Log.d(TAG, String.format("[%d] onStartBatchInput", mPointerId));
} }
synchronized (sAggregatedPointers) {
sAggregatedPointers.reset();
sLastRecognitionPointSize = 0;
sLastRecognitionTime = 0;
sListener.onStartBatchInput(); sListener.onStartBatchInput();
dismissAllMoreKeysPanels(); dismissAllMoreKeysPanels();
sTimerProxy.cancelLongPressTimerOf(this); sTimerProxy.cancelLongPressTimerOf(this);
} }
return true;
}
private void showGestureTrail() { private void showGestureTrail() {
if (mIsTrackingForActionDisabled) { if (mIsTrackingForActionDisabled) {
@ -610,55 +595,38 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
} }
public void updateBatchInputByTimer(final long syntheticMoveEventTime) { public void updateBatchInputByTimer(final long syntheticMoveEventTime) {
final int gestureTime = (int)(syntheticMoveEventTime - sGestureFirstDownTime); mBatchInputArbiter.updateBatchInputByTimer(syntheticMoveEventTime, this);
mGestureStrokeRecognitionPoints.duplicateLastPointWith(gestureTime);
updateBatchInput(syntheticMoveEventTime);
} }
private void updateBatchInput(final long moveEventTime) { // Implements {@link BatchInputArbiterListener}.
synchronized (sAggregatedPointers) { @Override
final GestureStrokeRecognitionPoints stroke = mGestureStrokeRecognitionPoints; public void onUpdateBatchInput(final InputPointers aggregatedPointers, final long eventTime) {
stroke.appendIncrementalBatchPoints(sAggregatedPointers);
final int size = sAggregatedPointers.getPointerSize();
if (size > sLastRecognitionPointSize
&& stroke.hasRecognitionTimePast(moveEventTime, sLastRecognitionTime)) {
if (DEBUG_LISTENER) { if (DEBUG_LISTENER) {
Log.d(TAG, String.format("[%d] onUpdateBatchInput: batchPoints=%d", mPointerId, Log.d(TAG, String.format("[%d] onUpdateBatchInput: batchPoints=%d", mPointerId,
size)); aggregatedPointers.getPointerSize()));
}
sTimerProxy.startUpdateBatchInputTimer(this);
sListener.onUpdateBatchInput(sAggregatedPointers);
// The listener may change the size of the pointers (when auto-committing
// for example), so we need to get the size from the pointers again.
sLastRecognitionPointSize = sAggregatedPointers.getPointerSize();
sLastRecognitionTime = moveEventTime;
}
} }
sListener.onUpdateBatchInput(aggregatedPointers);
} }
/** // Implements {@link BatchInputArbiterListener}.
* Determines whether the batch input has ended successfully or continues. @Override
* @param upEventTime the event time of this pointer up. public void onStartUpdateBatchInputTimer() {
* @return true if the batch input has ended successfully, false if it continues. sTimerProxy.startUpdateBatchInputTimer(this);
*/ }
private boolean mayEndBatchInput(final long upEventTime) {
boolean hasEndBatchInputSuccessfully = false; // Implements {@link BatchInputArbiterListener}.
synchronized (sAggregatedPointers) { @Override
mGestureStrokeRecognitionPoints.appendAllBatchPoints(sAggregatedPointers); public void onEndBatchInput(final InputPointers aggregatedPointers, final long eventTime) {
if (getActivePointerTrackerCount() == 1) { sTypingTimeRecorder.onEndBatchInput(eventTime);
hasEndBatchInputSuccessfully = true;
sTypingTimeRecorder.onEndBatchInput(upEventTime);
sTimerProxy.cancelAllUpdateBatchInputTimers(); sTimerProxy.cancelAllUpdateBatchInputTimers();
if (!mIsTrackingForActionDisabled) { if (mIsTrackingForActionDisabled) {
return;
}
if (DEBUG_LISTENER) { if (DEBUG_LISTENER) {
Log.d(TAG, String.format("[%d] onEndBatchInput : batchPoints=%d", Log.d(TAG, String.format("[%d] onEndBatchInput : batchPoints=%d",
mPointerId, sAggregatedPointers.getPointerSize())); mPointerId, aggregatedPointers.getPointerSize()));
} }
sListener.onEndBatchInput(sAggregatedPointers); sListener.onEndBatchInput(aggregatedPointers);
}
}
}
return hasEndBatchInputSuccessfully;
} }
private void cancelBatchInput() { private void cancelBatchInput() {
@ -753,15 +721,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
mIsDetectingGesture = (mKeyboard != null) && mKeyboard.mId.isAlphabetKeyboard() mIsDetectingGesture = (mKeyboard != null) && mKeyboard.mId.isAlphabetKeyboard()
&& key != null && !key.isModifier(); && key != null && !key.isModifier();
if (mIsDetectingGesture) { if (mIsDetectingGesture) {
if (getActivePointerTrackerCount() == 1) { mBatchInputArbiter.addDownEventPoint(x, y, eventTime,
sGestureFirstDownTime = eventTime; sTypingTimeRecorder.getLastLetterTypingTime(), getActivePointerTrackerCount());
} mGestureStrokeDrawingPoints.onDownEvent(
final int elapsedTimeSinceFirstDown = (int)(eventTime - sGestureFirstDownTime); x, y, mBatchInputArbiter.getElapsedTimeSinceFirstDown(eventTime));
final int elapsedTimeSinceLastTyping = (int)(
eventTime - sTypingTimeRecorder.getLastLetterTypingTime());
mGestureStrokeRecognitionPoints.onDownEvent(x, y, elapsedTimeSinceFirstDown,
elapsedTimeSinceLastTyping);
mGestureStrokeDrawingPoints.onDownEvent(x, y, elapsedTimeSinceFirstDown);
} }
} }
@ -820,31 +783,27 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
if (!mIsDetectingGesture) { if (!mIsDetectingGesture) {
return; return;
} }
final int beforeLength = mGestureStrokeRecognitionPoints.getLength(); final boolean onValidArea = mBatchInputArbiter.addMoveEventPoint(
final int elapsedTimeSinceFirstDown = (int)(eventTime - sGestureFirstDownTime); x, y, eventTime, isMajorEvent, this);
final boolean onValidArea = mGestureStrokeRecognitionPoints.addPointOnKeyboard(
x, y, elapsedTimeSinceFirstDown, isMajorEvent);
if (mGestureStrokeRecognitionPoints.getLength() > beforeLength) {
sTimerProxy.startUpdateBatchInputTimer(this);
}
// If the move event goes out from valid batch input area, cancel batch input. // If the move event goes out from valid batch input area, cancel batch input.
if (!onValidArea) { if (!onValidArea) {
cancelBatchInput(); cancelBatchInput();
return; return;
} }
mGestureStrokeDrawingPoints.onMoveEvent(x, y, elapsedTimeSinceFirstDown); mGestureStrokeDrawingPoints.onMoveEvent(
x, y, mBatchInputArbiter.getElapsedTimeSinceFirstDown(eventTime));
// If the MoreKeysPanel is showing then do not attempt to enter gesture mode. However, // If the MoreKeysPanel is showing then do not attempt to enter gesture mode. However,
// the gestured touch points are still being recorded in case the panel is dismissed. // the gestured touch points are still being recorded in case the panel is dismissed.
if (isShowingMoreKeysPanel()) { if (isShowingMoreKeysPanel()) {
return; return;
} }
if (!sInGesture && key != null && Character.isLetter(key.getCode()) if (!sInGesture && key != null && Character.isLetter(key.getCode())
&& mayStartBatchInput()) { && mBatchInputArbiter.mayStartBatchInput(this)) {
sInGesture = true; sInGesture = true;
} }
if (sInGesture) { if (sInGesture) {
if (key != null) { if (key != null) {
updateBatchInput(eventTime); mBatchInputArbiter.updateBatchInput(eventTime, this);
} }
showGestureTrail(); showGestureTrail();
} }
@ -1097,7 +1056,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
if (currentKey != null) { if (currentKey != null) {
callListenerOnRelease(currentKey, currentKey.getCode(), true /* withSliding */); callListenerOnRelease(currentKey, currentKey.getCode(), true /* withSliding */);
} }
if (mayEndBatchInput(eventTime)) { if (mBatchInputArbiter.mayEndBatchInput(
eventTime, getActivePointerTrackerCount(), this)) {
sInGesture = false; sInGesture = false;
} }
showGestureTrail(); showGestureTrail();

View file

@ -0,0 +1,181 @@
/*
* 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.keyboard.internal;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.InputPointers;
/**
* This class arbitrates batch input.
* An instance of this class holds a {@link GestureStrokeRecognitionPoints}.
* And it arbitrates multiple strokes gestured by multiple fingers and aggregates those gesture
* points into one batch input.
*/
public class BatchInputArbiter {
public interface BatchInputArbiterListener {
public void onStartBatchInput();
public void onUpdateBatchInput(
final InputPointers aggregatedPointers, final long moveEventTime);
public void onStartUpdateBatchInputTimer();
public void onEndBatchInput(final InputPointers aggregatedPointers, final long upEventTime);
}
// The starting time of the first stroke of a gesture input.
private static long sGestureFirstDownTime;
// The {@link InputPointers} that includes all events of a gesture input.
private static final InputPointers sAggregatedPointers = new InputPointers(
Constants.DEFAULT_GESTURE_POINTS_CAPACITY);
private static int sLastRecognitionPointSize = 0; // synchronized using sAggregatedPointers
private static long sLastRecognitionTime = 0; // synchronized using sAggregatedPointers
private final GestureStrokeRecognitionPoints mRecognitionPoints;
public BatchInputArbiter(final int pointerId, final GestureStrokeRecognitionParams params) {
mRecognitionPoints = new GestureStrokeRecognitionPoints(pointerId, params);
}
public void setKeyboardGeometry(final int keyWidth, final int keyboardHeight) {
mRecognitionPoints.setKeyboardGeometry(keyWidth, keyboardHeight);
}
/**
* Calculate elapsed time since the first gesture down.
* @param eventTime the time of this event.
* @return the elapsed time in millisecond from the first gesture down.
*/
public int getElapsedTimeSinceFirstDown(final long eventTime) {
return (int)(eventTime - sGestureFirstDownTime);
}
/**
* Add a down event point.
* @param x the x-coordinate of this down event.
* @param y the y-coordinate of this down event.
* @param downEventTime the time of this down event.
* @param lastLetterTypingTime the last typing input time.
* @param activePointerCount the number of active pointers when this pointer down event occurs.
*/
public void addDownEventPoint(final int x, final int y, final long downEventTime,
final long lastLetterTypingTime, final int activePointerCount) {
if (activePointerCount == 1) {
sGestureFirstDownTime = downEventTime;
}
final int elapsedTimeSinceFirstDown = getElapsedTimeSinceFirstDown(downEventTime);
final int elapsedTimeSinceLastTyping = (int)(downEventTime - lastLetterTypingTime);
mRecognitionPoints.addDownEventPoint(
x, y, elapsedTimeSinceFirstDown, elapsedTimeSinceLastTyping);
}
/**
* Add a move event point.
* @param x the x-coordinate of this move event.
* @param y the y-coordinate of this move event.
* @param moveEventTime the time of this move event.
* @param isMajorEvent false if this is a historical move event.
* @param listener {@link BatchInputArbiterListener#onStartUpdateBatchInputTimer()} of this
* <code>listener</code> may be called if enough move points have been added.
* @return true if this move event occurs on the valid gesture area.
*/
public boolean addMoveEventPoint(final int x, final int y, final long moveEventTime,
final boolean isMajorEvent, final BatchInputArbiterListener listener) {
final int beforeLength = mRecognitionPoints.getLength();
final boolean onValidArea = mRecognitionPoints.addEventPoint(
x, y, getElapsedTimeSinceFirstDown(moveEventTime), isMajorEvent);
if (mRecognitionPoints.getLength() > beforeLength) {
listener.onStartUpdateBatchInputTimer();
}
return onValidArea;
}
/**
* Determine whether the batch input has started or not.
* @param listener {@link BatchInputArbiterListener#onStartBatchInput()} of this
* <code>listener</code> will be called when the batch input has started successfully.
* @return true if the batch input has started successfully.
*/
public boolean mayStartBatchInput(final BatchInputArbiterListener listener) {
if (!mRecognitionPoints.isStartOfAGesture()) {
return false;
}
synchronized (sAggregatedPointers) {
sAggregatedPointers.reset();
sLastRecognitionPointSize = 0;
sLastRecognitionTime = 0;
listener.onStartBatchInput();
}
return true;
}
/**
* Add synthetic move event point. After adding the point,
* {@link #updateBatchInput(long,BatchInputArbiterListener)} will be called internally.
* @param syntheticMoveEventTime the synthetic move event time.
* @param listener the listener to be passed to
* {@link #updateBatchInput(long,BatchInputArbiterListener)}.
*/
public void updateBatchInputByTimer(final long syntheticMoveEventTime,
final BatchInputArbiterListener listener) {
mRecognitionPoints.duplicateLastPointWith(
getElapsedTimeSinceFirstDown(syntheticMoveEventTime));
updateBatchInput(syntheticMoveEventTime, listener);
}
/**
* Determine whether we have enough gesture points to lookup dictionary.
* @param moveEventTime the time of this move event.
* @param listener {@link BatchInputArbiterListener#onUpdateBatchInput(InputPointers,long)} of
* this <code>listener</code> will be called when enough event points we have. Also
* {@link BatchInputArbiterListener#onStartUpdateBatchInputTimer()} will be called to have
* possible future synthetic move event.
*/
public void updateBatchInput(final long moveEventTime,
final BatchInputArbiterListener listener) {
synchronized (sAggregatedPointers) {
mRecognitionPoints.appendIncrementalBatchPoints(sAggregatedPointers);
final int size = sAggregatedPointers.getPointerSize();
if (size > sLastRecognitionPointSize && mRecognitionPoints.hasRecognitionTimePast(
moveEventTime, sLastRecognitionTime)) {
listener.onUpdateBatchInput(sAggregatedPointers, moveEventTime);
listener.onStartUpdateBatchInputTimer();
// The listener may change the size of the pointers (when auto-committing
// for example), so we need to get the size from the pointers again.
sLastRecognitionPointSize = sAggregatedPointers.getPointerSize();
sLastRecognitionTime = moveEventTime;
}
}
}
/**
* Determine whether the batch input has ended successfully or continues.
* @param upEventTime the time of this up event.
* @param activePointerCount the number of active pointers when this pointer up event occurs.
* @param listener {@link BatchInputArbiterListener#onEndBatchInput(InputPointers,long)} of this
* <code>listener</code> will be called when the batch input has started successfully.
* @return true if the batch input has ended successfully.
*/
public boolean mayEndBatchInput(final long upEventTime, final int activePointerCount,
final BatchInputArbiterListener listener) {
synchronized (sAggregatedPointers) {
mRecognitionPoints.appendAllBatchPoints(sAggregatedPointers);
if (activePointerCount == 1) {
listener.onEndBatchInput(sAggregatedPointers, upEventTime);
return true;
}
}
return false;
}
}

View file

@ -18,14 +18,15 @@ package com.android.inputmethod.keyboard.internal;
import android.util.Log; import android.util.Log;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.InputPointers; import com.android.inputmethod.latin.InputPointers;
import com.android.inputmethod.latin.utils.ResizableIntArray; import com.android.inputmethod.latin.utils.ResizableIntArray;
/** /**
* This class holds event points to recognize a gesture stroke. * This class holds event points to recognize a gesture stroke.
* TODO: Should be final and package private class. * TODO: Should be package private class.
*/ */
public class GestureStrokeRecognitionPoints { public final class GestureStrokeRecognitionPoints {
private static final String TAG = GestureStrokeRecognitionPoints.class.getSimpleName(); private static final String TAG = GestureStrokeRecognitionPoints.class.getSimpleName();
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
private static final boolean DEBUG_SPEED = false; private static final boolean DEBUG_SPEED = false;
@ -34,12 +35,13 @@ public class GestureStrokeRecognitionPoints {
// Proportional to the keyboard height. // Proportional to the keyboard height.
public static final float EXTRA_GESTURE_TRAIL_AREA_ABOVE_KEYBOARD_RATIO = 0.25f; public static final float EXTRA_GESTURE_TRAIL_AREA_ABOVE_KEYBOARD_RATIO = 0.25f;
public static final int DEFAULT_CAPACITY = 128;
private final int mPointerId; private final int mPointerId;
private final ResizableIntArray mEventTimes = new ResizableIntArray(DEFAULT_CAPACITY); private final ResizableIntArray mEventTimes = new ResizableIntArray(
private final ResizableIntArray mXCoordinates = new ResizableIntArray(DEFAULT_CAPACITY); Constants.DEFAULT_GESTURE_POINTS_CAPACITY);
private final ResizableIntArray mYCoordinates = new ResizableIntArray(DEFAULT_CAPACITY); private final ResizableIntArray mXCoordinates = new ResizableIntArray(
Constants.DEFAULT_GESTURE_POINTS_CAPACITY);
private final ResizableIntArray mYCoordinates = new ResizableIntArray(
Constants.DEFAULT_GESTURE_POINTS_CAPACITY);
private final GestureStrokeRecognitionParams mRecognitionParams; private final GestureStrokeRecognitionParams mRecognitionParams;
@ -67,12 +69,14 @@ public class GestureStrokeRecognitionPoints {
private static final int MSEC_PER_SEC = 1000; private static final int MSEC_PER_SEC = 1000;
// TODO: Make this package private
public GestureStrokeRecognitionPoints(final int pointerId, public GestureStrokeRecognitionPoints(final int pointerId,
final GestureStrokeRecognitionParams recognitionParams) { final GestureStrokeRecognitionParams recognitionParams) {
mPointerId = pointerId; mPointerId = pointerId;
mRecognitionParams = recognitionParams; mRecognitionParams = recognitionParams;
} }
// TODO: Make this package private
public void setKeyboardGeometry(final int keyWidth, final int keyboardHeight) { public void setKeyboardGeometry(final int keyWidth, final int keyboardHeight) {
mKeyWidth = keyWidth; mKeyWidth = keyWidth;
mMinYCoordinate = -(int)(keyboardHeight * EXTRA_GESTURE_TRAIL_AREA_ABOVE_KEYBOARD_RATIO); mMinYCoordinate = -(int)(keyboardHeight * EXTRA_GESTURE_TRAIL_AREA_ABOVE_KEYBOARD_RATIO);
@ -99,11 +103,13 @@ public class GestureStrokeRecognitionPoints {
} }
} }
// TODO: Make this package private
public int getLength() { public int getLength() {
return mEventTimes.getLength(); return mEventTimes.getLength();
} }
public void onDownEvent(final int x, final int y, final int elapsedTimeSinceFirstDown, // TODO: Make this package private
public void addDownEventPoint(final int x, final int y, final int elapsedTimeSinceFirstDown,
final int elapsedTimeSinceLastTyping) { final int elapsedTimeSinceLastTyping) {
reset(); reset();
if (elapsedTimeSinceLastTyping < mRecognitionParams.mStaticTimeThresholdAfterFastTyping) { if (elapsedTimeSinceLastTyping < mRecognitionParams.mStaticTimeThresholdAfterFastTyping) {
@ -113,7 +119,9 @@ public class GestureStrokeRecognitionPoints {
Log.d(TAG, String.format("[%d] onDownEvent: dT=%3d%s", mPointerId, Log.d(TAG, String.format("[%d] onDownEvent: dT=%3d%s", mPointerId,
elapsedTimeSinceLastTyping, mAfterFastTyping ? " afterFastTyping" : "")); elapsedTimeSinceLastTyping, mAfterFastTyping ? " afterFastTyping" : ""));
} }
addPointOnKeyboard(x, y, elapsedTimeSinceFirstDown, true /* isMajorEvent */); // Call {@link #addEventPoint(int,int,int,boolean)} to record this down event point as a
// major event point.
addEventPoint(x, y, elapsedTimeSinceFirstDown, true /* isMajorEvent */);
} }
private int getGestureDynamicDistanceThreshold(final int deltaTime) { private int getGestureDynamicDistanceThreshold(final int deltaTime) {
@ -137,6 +145,7 @@ public class GestureStrokeRecognitionPoints {
return mRecognitionParams.mDynamicTimeThresholdFrom - decayedThreshold; return mRecognitionParams.mDynamicTimeThresholdFrom - decayedThreshold;
} }
// TODO: Make this package private
public final boolean isStartOfAGesture() { public final boolean isStartOfAGesture() {
if (!hasDetectedFastMove()) { if (!hasDetectedFastMove()) {
return false; return false;
@ -167,6 +176,7 @@ public class GestureStrokeRecognitionPoints {
return isStartOfAGesture; return isStartOfAGesture;
} }
// TODO: Make this package private
public void duplicateLastPointWith(final int time) { public void duplicateLastPointWith(final int time) {
final int lastIndex = getLength() - 1; final int lastIndex = getLength() - 1;
if (lastIndex >= 0) { if (lastIndex >= 0) {
@ -250,19 +260,20 @@ public class GestureStrokeRecognitionPoints {
} }
/** /**
* Add a touch event as a gesture point. Returns true if the touch event is on the valid * Add an event point to this gesture stroke recognition points. Returns true if the event
* gesture area. * point is on the valid gesture area.
* @param x the x-coordinate of the touch event * @param x the x-coordinate of the event point
* @param y the y-coordinate of the touch event * @param y the y-coordinate of the event point
* @param time the elapsed time in millisecond from the first gesture down * @param time the elapsed time in millisecond from the first gesture down
* @param isMajorEvent false if this is a historical move event * @param isMajorEvent false if this is a historical move event
* @return true if the touch event is on the valid gesture area * @return true if the event point is on the valid gesture area
*/ */
public boolean addPointOnKeyboard(final int x, final int y, final int time, // TODO: Make this package private
public boolean addEventPoint(final int x, final int y, final int time,
final boolean isMajorEvent) { final boolean isMajorEvent) {
final int size = getLength(); final int size = getLength();
if (size <= 0) { if (size <= 0) {
// Down event // The first event of this stroke (a.k.a. down event).
appendPoint(x, y, time); appendPoint(x, y, time);
updateMajorEvent(x, y, time); updateMajorEvent(x, y, time);
} else { } else {
@ -291,15 +302,18 @@ public class GestureStrokeRecognitionPoints {
} }
} }
// TODO: Make this package private
public final boolean hasRecognitionTimePast( public final boolean hasRecognitionTimePast(
final long currentTime, final long lastRecognitionTime) { final long currentTime, final long lastRecognitionTime) {
return currentTime > lastRecognitionTime + mRecognitionParams.mRecognitionMinimumTime; return currentTime > lastRecognitionTime + mRecognitionParams.mRecognitionMinimumTime;
} }
// TODO: Make this package private
public final void appendAllBatchPoints(final InputPointers out) { public final void appendAllBatchPoints(final InputPointers out) {
appendBatchPoints(out, getLength()); appendBatchPoints(out, getLength());
} }
// TODO: Make this package private
public final void appendIncrementalBatchPoints(final InputPointers out) { public final void appendIncrementalBatchPoints(final InputPointers out) {
appendBatchPoints(out, mIncrementalRecognitionSize); appendBatchPoints(out, mIncrementalRecognitionSize);
} }

View file

@ -257,6 +257,13 @@ public final class Constants {
public static final int SCREEN_METRICS_LARGE_TABLET = 2; public static final int SCREEN_METRICS_LARGE_TABLET = 2;
public static final int SCREEN_METRICS_SMALL_TABLET = 3; public static final int SCREEN_METRICS_SMALL_TABLET = 3;
/**
* Default capacity of gesture points container.
* This constant is used by {@link BatchInputArbiter} and etc. to preallocate regions that
* contain gesture event points.
*/
public static final int DEFAULT_GESTURE_POINTS_CAPACITY = 128;
private Constants() { private Constants() {
// This utility class is not publicly instantiable. // This utility class is not publicly instantiable.
} }