Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80bcb996 authored by Tadashi G. Takaoka's avatar Tadashi G. Takaoka
Browse files

Move gesture detection and recognition paramters to resources

Bug: 7032858
Change-Id: I66570a5e21cdeede1eba420c597f440ab61aa941
parent 20f07e33
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -127,6 +127,23 @@
        <attr name="ignoreAltCodeKeyTimeout" format="integer" />
        <!-- More keys keyboard will shown at touched point. -->
        <attr name="showMoreKeysKeyboardAtTouchedPoint" format="boolean" />
        <!-- Static threshold for gesture after fast typing (msec) -->
        <attr name="gestureStaticTimeThresholdAfterFastTyping" format="integer" />
        <!-- Static threshold for starting gesture detection (keyWidth%/sec) -->
        <attr name="gestureDetectFastMoveSpeedThreshold" format="fraction" />
        <!-- Dynamic threshold for gesture after fast typing (msec) -->
        <attr name="gestureDynamicThresholdDecayDuration" format="integer" />
        <!-- Time based threshold values for gesture detection (msec) -->
        <attr name="gestureDynamicTimeThresholdFrom" format="integer" />
        <attr name="gestureDynamicTimeThresholdTo" format="integer" />
        <!-- Distance based threshold values for gesture detection (keyWidth%/sec) -->
        <attr name="gestureDynamicDistanceThresholdFrom" format="fraction" />
        <attr name="gestureDynamicDistanceThresholdTo" format="fraction" />
        <!-- Parameter for gesture sampling (keyWidth%/sec) -->
        <attr name="gestureSamplingMinimumDistance" format="fraction" />
        <!-- Parameters for gesture recognition (msec) and (keyWidth%/sec) -->
        <attr name="gestureRecognitionMinimumTime" format="integer" />
        <attr name="gestureRecognitionSpeedThreshold" format="fraction" />
    </declare-styleable>

    <declare-styleable name="SuggestionStripView">
+17 −0
Original line number Diff line number Diff line
@@ -69,6 +69,23 @@
    <!-- Showing more keys keyboard, just above the touched point if true, aligned to the key if
         false -->
    <bool name="config_show_more_keys_keyboard_at_touched_point">false</bool>
    <!-- Static threshold for gesture after fast typing (msec) -->
    <integer name="config_gesture_static_time_threshold_after_fast_typing">350</integer>
    <!-- Static threshold for starting gesture detection (keyWidth%/sec) -->
    <fraction name="config_gesture_detect_fast_move_speed_threshold">150%</fraction>
    <!-- Dynamic threshold for gesture after fast typing (msec) -->
    <integer name="config_gesture_dynamic_threshold_decay_duration">450</integer>
    <!-- Time based threshold values for gesture detection (msec) -->
    <integer name="config_gesture_dynamic_time_threshold_from">300</integer>
    <integer name="config_gesture_dynamic_time_threshold_to">20</integer>
    <!-- Distance based threshold values for gesture detection (keyWidth%/sec) -->
    <fraction name="config_gesture_dynamic_distance_threshold_from">600%</fraction>
    <fraction name="config_gesture_dynamic_distance_threshold_to">35%</fraction>
    <!-- Parameter for gesture sampling (keyWidth%/sec) -->
    <fraction name="config_gesture_sampling_minimum_distance">16.6666%</fraction>
    <!-- Parameters for gesture recognition (msec) and (keyWidth%/sec) -->
    <integer name="config_gesture_recognition_minimum_time">100</integer>
    <fraction name="config_gesture_recognition_speed_threshold">550%</fraction>
    <!--
        Configuration for auto correction
     -->
+11 −0
Original line number Diff line number Diff line
@@ -94,6 +94,17 @@
        <item name="languageOnSpacebarFadeoutAnimator">@anim/language_on_spacebar_fadeout</item>
        <item name="altCodeKeyWhileTypingFadeoutAnimator">@anim/alt_code_key_while_typing_fadeout</item>
        <item name="altCodeKeyWhileTypingFadeinAnimator">@anim/alt_code_key_while_typing_fadein</item>
        <!-- Common attributes of MainKeyboardView for gesture typing detection and recognition -->
        <item name="gestureStaticTimeThresholdAfterFastTyping">@integer/config_gesture_static_time_threshold_after_fast_typing</item>
        <item name="gestureDetectFastMoveSpeedThreshold">@fraction/config_gesture_detect_fast_move_speed_threshold</item>
        <item name="gestureDynamicThresholdDecayDuration">@integer/config_gesture_dynamic_threshold_decay_duration</item>
        <item name="gestureDynamicTimeThresholdFrom">@integer/config_gesture_dynamic_time_threshold_from</item>
        <item name="gestureDynamicTimeThresholdTo">@integer/config_gesture_dynamic_time_threshold_to</item>
        <item name="gestureDynamicDistanceThresholdFrom">@fraction/config_gesture_dynamic_distance_threshold_from</item>
        <item name="gestureDynamicDistanceThresholdTo">@fraction/config_gesture_dynamic_distance_threshold_to</item>
        <item name="gestureSamplingMinimumDistance">@fraction/config_gesture_sampling_minimum_distance</item>
        <item name="gestureRecognitionMinimumTime">@integer/config_gesture_recognition_minimum_time</item>
        <item name="gestureRecognitionSpeedThreshold">@fraction/config_gesture_recognition_speed_threshold</item>
    </style>
    <style
        name="MainKeyboardView"
+10 −4
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.view.MotionEvent;

import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.keyboard.internal.GestureStroke;
import com.android.inputmethod.keyboard.internal.GestureStroke.GestureStrokeParams;
import com.android.inputmethod.keyboard.internal.GestureStrokeWithPreviewPoints;
import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
import com.android.inputmethod.latin.CollectionUtils;
@@ -135,7 +136,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
            mTouchNoiseThresholdDistanceSquared = 0;
        }

        public PointerTrackerParams(TypedArray mainKeyboardViewAttr) {
        public PointerTrackerParams(final TypedArray mainKeyboardViewAttr) {
            mSlidingKeyInputEnabled = mainKeyboardViewAttr.getBoolean(
                    R.styleable.MainKeyboardView_slidingKeyInputEnable, false);
            mTouchNoiseThresholdTime = mainKeyboardViewAttr.getInt(
@@ -150,6 +151,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {

    // Parameters for pointer handling.
    private static PointerTrackerParams sParams;
    private static GestureStrokeParams sGestureStrokeParams;
    private static boolean sNeedsPhantomSuddenMoveEventHack;

    private static final ArrayList<PointerTracker> sTrackers = CollectionUtils.newArrayList();
@@ -222,10 +224,12 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
        }
        sNeedsPhantomSuddenMoveEventHack = needsPhantomSuddenMoveEventHack;
        sParams = PointerTrackerParams.DEFAULT;
        sGestureStrokeParams = GestureStrokeParams.DEFAULT;
    }

    public static void setParameters(final TypedArray mainKeyboardViewAttr) {
        sParams = new PointerTrackerParams(mainKeyboardViewAttr);
        sGestureStrokeParams = new GestureStrokeParams(mainKeyboardViewAttr);
    }

    private static void updateGestureHandlingMode() {
@@ -296,7 +300,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
            throw new NullPointerException();
        }
        mPointerId = id;
        mGestureStrokeWithPreviewPoints = new GestureStrokeWithPreviewPoints(id);
        mGestureStrokeWithPreviewPoints = new GestureStrokeWithPreviewPoints(
                id, sGestureStrokeParams);
        setKeyDetectorInner(handler.getKeyDetector());
        mListener = handler.getKeyboardActionListener();
        mDrawingProxy = handler.getDrawingProxy();
@@ -587,10 +592,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
    private void mayUpdateBatchInput(final long eventTime, final Key key) {
        if (key != null) {
            synchronized (sAggregratedPointers) {
                mGestureStrokeWithPreviewPoints.appendIncrementalBatchPoints(sAggregratedPointers);
                final GestureStroke stroke = mGestureStrokeWithPreviewPoints;
                stroke.appendIncrementalBatchPoints(sAggregratedPointers);
                final int size = sAggregratedPointers.getPointerSize();
                if (size > sLastRecognitionPointSize
                        && GestureStroke.hasRecognitionTimePast(eventTime, sLastRecognitionTime)) {
                        && stroke.hasRecognitionTimePast(eventTime, sLastRecognitionTime)) {
                    sLastRecognitionPointSize = size;
                    sLastRecognitionTime = eventTime;
                    if (DEBUG_LISTENER) {
+92 −40
Original line number Diff line number Diff line
@@ -14,10 +14,13 @@

package com.android.inputmethod.keyboard.internal;

import android.content.res.TypedArray;
import android.util.Log;

import com.android.inputmethod.latin.InputPointers;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.ResizableIntArray;
import com.android.inputmethod.latin.ResourceUtils;

public class GestureStroke {
    private static final String TAG = GestureStroke.class.getSimpleName();
@@ -31,6 +34,8 @@ public class GestureStroke {
    private final ResizableIntArray mXCoordinates = new ResizableIntArray(DEFAULT_CAPACITY);
    private final ResizableIntArray mYCoordinates = new ResizableIntArray(DEFAULT_CAPACITY);

    private final GestureStrokeParams mParams;

    private int mKeyWidth; // pixel
    // Static threshold for starting gesture detection
    private int mDetectFastMoveSpeedThreshold; // pixel /sec
@@ -51,53 +56,100 @@ public class GestureStroke {
    private int mIncrementalRecognitionSize;
    private int mLastIncrementalBatchSize;

    // TODO: Move some of these to resource.

    public static final class GestureStrokeParams {
        // Static threshold for gesture after fast typing
    public static final int GESTURE_STATIC_TIME_THRESHOLD_AFTER_FAST_TYPING = 350; // msec

        public final int mStaticTimeThresholdAfterFastTyping; // msec
        // Static threshold for starting gesture detection
    private static final float DETECT_FAST_MOVE_SPEED_THRESHOLD = 1.5f; // keyWidth / sec

        public final float mDetectFastMoveSpeedThreshold; // keyWidth/sec
        // Dynamic threshold for gesture after fast typing
    private static final int GESTURE_DYNAMIC_THRESHOLD_DECAY_DURATION = 450; // msec
        public final int mDynamicThresholdDecayDuration; // msec
        // Time based threshold values
    private static final int GESTURE_DYNAMIC_TIME_THRESHOLD_FROM = 300; // msec
    private static final int GESTURE_DYNAMIC_TIME_THRESHOLD_TO = 20; // msec
        public final int mDynamicTimeThresholdFrom; // msec
        public final int mDynamicTimeThresholdTo; // msec
        // Distance based threshold values
    private static final float GESTURE_DYNAMIC_DISTANCE_THRESHOLD_FROM = 6.0f; // keyWidth
    private static final float GESTURE_DYNAMIC_DISTANCE_THRESHOLD_TO = 0.35f; // keyWidth

        public final float mDynamicDistanceThresholdFrom; // keyWidth
        public final float mDynamicDistanceThresholdTo; // keyWidth
        // Parameters for gesture sampling
    private static final float GESTURE_SAMPLING_MINIMUM_DISTANCE = 1.0f / 6.0f; // keyWidth

        public final float mSamplingMinimumDistance; // keyWidth
        // Parameters for gesture recognition
    private static final int GESTURE_RECOGNITION_MINIMUM_TIME = 100; // msec
    private static final float GESTURE_RECOGNITION_SPEED_THRESHOLD = 5.5f; // keyWidth / sec
        public final int mRecognitionMinimumTime; // msec
        public final float mRecognitionSpeedThreshold; // keyWidth/sec

        // Default GestureStroke parameters for test.
        public static final GestureStrokeParams FOR_TEST = new GestureStrokeParams();
        public static final GestureStrokeParams DEFAULT = FOR_TEST;

        private GestureStrokeParams() {
            // These parameter values are default and intended for testing.
            mStaticTimeThresholdAfterFastTyping = 350; // msec
            mDetectFastMoveSpeedThreshold = 1.5f; // keyWidth / sec
            mDynamicThresholdDecayDuration = 450; // msec
            mDynamicTimeThresholdFrom = 300; // msec
            mDynamicTimeThresholdTo = 20; // msec
            mDynamicDistanceThresholdFrom = 6.0f; // keyWidth
            mDynamicDistanceThresholdTo = 0.35f; // keyWidth
            // The following parameters' change will affect the result of regression test.
            mSamplingMinimumDistance = 1.0f / 6.0f; // keyWidth
            mRecognitionMinimumTime = 100; // msec
            mRecognitionSpeedThreshold = 5.5f; // keyWidth / sec
        }

        public GestureStrokeParams(final TypedArray mainKeyboardViewAttr) {
            mStaticTimeThresholdAfterFastTyping = mainKeyboardViewAttr.getInt(
                    R.styleable.MainKeyboardView_gestureStaticTimeThresholdAfterFastTyping,
                    DEFAULT.mStaticTimeThresholdAfterFastTyping);
            mDetectFastMoveSpeedThreshold = ResourceUtils.getFraction(mainKeyboardViewAttr,
                    R.styleable.MainKeyboardView_gestureDetectFastMoveSpeedThreshold,
                    DEFAULT.mDetectFastMoveSpeedThreshold);
            mDynamicThresholdDecayDuration = mainKeyboardViewAttr.getInt(
                    R.styleable.MainKeyboardView_gestureDynamicThresholdDecayDuration,
                    DEFAULT.mDynamicThresholdDecayDuration);
            mDynamicTimeThresholdFrom = mainKeyboardViewAttr.getInt(
                    R.styleable.MainKeyboardView_gestureDynamicTimeThresholdFrom,
                    DEFAULT.mDynamicTimeThresholdFrom);
            mDynamicTimeThresholdTo = mainKeyboardViewAttr.getInt(
                    R.styleable.MainKeyboardView_gestureDynamicTimeThresholdTo,
                    DEFAULT.mDynamicTimeThresholdTo);
            mDynamicDistanceThresholdFrom = ResourceUtils.getFraction(mainKeyboardViewAttr,
                    R.styleable.MainKeyboardView_gestureDynamicDistanceThresholdFrom,
                    DEFAULT.mDynamicDistanceThresholdFrom);
            mDynamicDistanceThresholdTo = ResourceUtils.getFraction(mainKeyboardViewAttr,
                    R.styleable.MainKeyboardView_gestureDynamicDistanceThresholdTo,
                    DEFAULT.mDynamicDistanceThresholdTo);
            mSamplingMinimumDistance = ResourceUtils.getFraction(mainKeyboardViewAttr,
                    R.styleable.MainKeyboardView_gestureSamplingMinimumDistance,
                    DEFAULT.mSamplingMinimumDistance);
            mRecognitionMinimumTime = mainKeyboardViewAttr.getInt(
                    R.styleable.MainKeyboardView_gestureRecognitionMinimumTime,
                    DEFAULT.mRecognitionMinimumTime);
            mRecognitionSpeedThreshold = ResourceUtils.getFraction(mainKeyboardViewAttr,
                    R.styleable.MainKeyboardView_gestureRecognitionSpeedThreshold,
                    DEFAULT.mRecognitionSpeedThreshold);
        }
    }

    private static final int MSEC_PER_SEC = 1000;

    public GestureStroke(final int pointerId) {
    public GestureStroke(final int pointerId, final GestureStrokeParams params) {
        mPointerId = pointerId;
        mParams = params;
    }

    public void setKeyboardGeometry(final int keyWidth) {
        mKeyWidth = keyWidth;
        // TODO: Find an appropriate base metric for these length. Maybe diagonal length of the key?
        mDetectFastMoveSpeedThreshold = (int)(keyWidth * DETECT_FAST_MOVE_SPEED_THRESHOLD);
        mDetectFastMoveSpeedThreshold = (int)(keyWidth * mParams.mDetectFastMoveSpeedThreshold);
        mGestureDynamicDistanceThresholdFrom =
                (int)(keyWidth * GESTURE_DYNAMIC_DISTANCE_THRESHOLD_FROM);
        mGestureDynamicDistanceThresholdTo =
                (int)(keyWidth * GESTURE_DYNAMIC_DISTANCE_THRESHOLD_TO);
        mGestureSamplingMinimumDistance = (int)(keyWidth * GESTURE_SAMPLING_MINIMUM_DISTANCE);
        mGestureRecognitionSpeedThreshold =
                (int)(keyWidth * GESTURE_RECOGNITION_SPEED_THRESHOLD);
                (int)(keyWidth * mParams.mDynamicDistanceThresholdFrom);
        mGestureDynamicDistanceThresholdTo = (int)(keyWidth * mParams.mDynamicDistanceThresholdTo);
        mGestureSamplingMinimumDistance = (int)(keyWidth * mParams.mSamplingMinimumDistance);
        mGestureRecognitionSpeedThreshold = (int)(keyWidth * mParams.mRecognitionSpeedThreshold);
        if (DEBUG) {
            Log.d(TAG, String.format(
                    "[%d] setKeyboardGeometry: keyWidth=%3d tT=%3d >> %3d tD=%3d >> %3d",
                    mPointerId, keyWidth,
                    GESTURE_DYNAMIC_TIME_THRESHOLD_FROM,
                    GESTURE_DYNAMIC_TIME_THRESHOLD_TO,
                    mParams.mDynamicTimeThresholdFrom,
                    mParams.mDynamicTimeThresholdTo,
                    mGestureDynamicDistanceThresholdFrom,
                    mGestureDynamicDistanceThresholdTo));
        }
@@ -107,7 +159,7 @@ public class GestureStroke {
            final long gestureFirstDownTime, final long lastTypingTime) {
        reset();
        final long elapsedTimeAfterTyping = downTime - lastTypingTime;
        if (elapsedTimeAfterTyping < GESTURE_STATIC_TIME_THRESHOLD_AFTER_FAST_TYPING) {
        if (elapsedTimeAfterTyping < mParams.mStaticTimeThresholdAfterFastTyping) {
            mAfterFastTyping = true;
        }
        if (DEBUG) {
@@ -119,23 +171,23 @@ public class GestureStroke {
    }

    private int getGestureDynamicDistanceThreshold(final int deltaTime) {
        if (!mAfterFastTyping || deltaTime >= GESTURE_DYNAMIC_THRESHOLD_DECAY_DURATION) {
        if (!mAfterFastTyping || deltaTime >= mParams.mDynamicThresholdDecayDuration) {
            return mGestureDynamicDistanceThresholdTo;
        }
        final int decayedThreshold =
                (mGestureDynamicDistanceThresholdFrom - mGestureDynamicDistanceThresholdTo)
                * deltaTime / GESTURE_DYNAMIC_THRESHOLD_DECAY_DURATION;
                * deltaTime / mParams.mDynamicThresholdDecayDuration;
        return mGestureDynamicDistanceThresholdFrom - decayedThreshold;
    }

    private int getGestureDynamicTimeThreshold(final int deltaTime) {
        if (!mAfterFastTyping || deltaTime >= GESTURE_DYNAMIC_THRESHOLD_DECAY_DURATION) {
            return GESTURE_DYNAMIC_TIME_THRESHOLD_TO;
        if (!mAfterFastTyping || deltaTime >= mParams.mDynamicThresholdDecayDuration) {
            return mParams.mDynamicTimeThresholdTo;
        }
        final int decayedThreshold =
                (GESTURE_DYNAMIC_TIME_THRESHOLD_FROM - GESTURE_DYNAMIC_TIME_THRESHOLD_TO)
                * deltaTime / GESTURE_DYNAMIC_THRESHOLD_DECAY_DURATION;
        return GESTURE_DYNAMIC_TIME_THRESHOLD_FROM - decayedThreshold;
                (mParams.mDynamicTimeThresholdFrom - mParams.mDynamicTimeThresholdTo)
                * deltaTime / mParams.mDynamicThresholdDecayDuration;
        return mParams.mDynamicTimeThresholdFrom - decayedThreshold;
    }

    public boolean isStartOfAGesture() {
@@ -249,9 +301,9 @@ public class GestureStroke {
        }
    }

    public static final boolean hasRecognitionTimePast(
    public final boolean hasRecognitionTimePast(
            final long currentTime, final long lastRecognitionTime) {
        return currentTime > lastRecognitionTime + GESTURE_RECOGNITION_MINIMUM_TIME;
        return currentTime > lastRecognitionTime + mParams.mRecognitionMinimumTime;
    }

    public void appendAllBatchPoints(final InputPointers out) {
Loading