aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/keyboard/internal/BatchInputArbiter.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/keyboard/internal/BatchInputArbiter.java')
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/BatchInputArbiter.java181
1 files changed, 181 insertions, 0 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/internal/BatchInputArbiter.java b/java/src/com/android/inputmethod/keyboard/internal/BatchInputArbiter.java
new file mode 100644
index 000000000..cd9875955
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/BatchInputArbiter.java
@@ -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;
+ }
+}