Merge "Add BatchInputArbiter"
This commit is contained in:
commit
3fbcf48591
4 changed files with 269 additions and 107 deletions
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue