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

Commit 6ae8dd43 authored by Satoshi Kataoka's avatar Satoshi Kataoka Committed by satok
Browse files

Tweak beeline speed

Change-Id: I77bbd5e1888281e838d87824dc04a574b1a7ecb7
parent 9b935084
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -86,7 +86,7 @@
    <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>
    <integer name="config_gesture_recognition_update_time">300</integer>
    <integer name="config_gesture_recognition_update_time">100</integer>
    <fraction name="config_gesture_recognition_speed_threshold">550%</fraction>
    <!-- Suppress showing key preview duration after batch input in millisecond -->
    <integer name="config_suppress_key_preview_after_batch_input_duration">1000</integer>
+11 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.inputmethod.latin;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
@@ -42,6 +43,7 @@ public final class DebugSettings extends PreferenceFragment

    private boolean mServiceNeedsRestart = false;
    private CheckBoxPreference mDebugMode;
    private CheckBoxPreference mStatisticsLoggingPref;

    @Override
    public void onCreate(Bundle icicle) {
@@ -59,6 +61,7 @@ public final class DebugSettings extends PreferenceFragment
        }
        final Preference statisticsLoggingPref = findPreference(PREF_STATISTICS_LOGGING_KEY);
        if (statisticsLoggingPref instanceof CheckBoxPreference) {
            mStatisticsLoggingPref = (CheckBoxPreference) statisticsLoggingPref;
            if (!SHOW_STATISTICS_LOGGING) {
                getPreferenceScreen().removePreference(statisticsLoggingPref);
            }
@@ -80,6 +83,14 @@ public final class DebugSettings extends PreferenceFragment
        if (key.equals(DEBUG_MODE_KEY)) {
            if (mDebugMode != null) {
                mDebugMode.setChecked(prefs.getBoolean(DEBUG_MODE_KEY, false));
                final boolean checked = mDebugMode.isChecked();
                if (mStatisticsLoggingPref != null) {
                    if (checked) {
                        getPreferenceScreen().addPreference(mStatisticsLoggingPref);
                    } else {
                        getPreferenceScreen().removePreference(mStatisticsLoggingPref);
                    }
                }
                updateDebugMode();
                mServiceNeedsRestart = true;
            }
+6 −0
Original line number Diff line number Diff line
@@ -423,4 +423,10 @@ typedef enum {
    // Additional proximity char which can differ by language.
    ADDITIONAL_PROXIMITY_CHAR
} ProximityType;

typedef enum {
    NOT_A_DOUBLE_LETTER,
    A_DOUBLE_LETTER,
    A_STRONG_DOUBLE_LETTER
} DoubleLetterLevel;
#endif // LATINIME_DEFINES_H
+61 −24
Original line number Diff line number Diff line
@@ -31,6 +31,10 @@ const int ProximityInfoState::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR =
        1 << NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
const float ProximityInfoState::NOT_A_DISTANCE_FLOAT = -1.0f;
const int ProximityInfoState::NOT_A_CODE = -1;
const int ProximityInfoState::LOOKUP_RADIUS_PERCENTILE = 50;
const int ProximityInfoState::FIRST_POINT_TIME_OFFSET_MILLIS = 150;
const int ProximityInfoState::STRONG_DOUBLE_LETTER_TIME_MILLIS = 600;
const int ProximityInfoState::MIN_DOUBLE_LETTER_BEELINE_SPEED_PERCENTILE = 5;

void ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength,
        const ProximityInfo *proximityInfo, const int *const inputCodes, const int inputSize,
@@ -105,7 +109,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
        mNearKeysVector.clear();
        mSearchKeysVector.clear();
        mSpeedRates.clear();
        mBeelineSpeedRates.clear();
        mBeelineSpeedPercentiles.clear();
        mCharProbabilities.clear();
        mDirections.clear();
    }
@@ -253,9 +257,9 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
        AKLOGI("===== sampled points =====");
        for (int i = 0; i < mSampledInputSize; ++i) {
            if (isGeometric) {
                AKLOGI("%d: x = %d, y = %d, time = %d, relative speed = %.4f, beeline speed = %.4f",
                AKLOGI("%d: x = %d, y = %d, time = %d, relative speed = %.4f, beeline speed = %d",
                        i, mSampledInputXs[i], mSampledInputYs[i], mTimes[i], mSpeedRates[i],
                        getBeelineSpeedRate(i));
                        getBeelineSpeedPercentile(i));
            }
            sampledX << mSampledInputXs[i];
            sampledY << mSampledInputYs[i];
@@ -366,54 +370,65 @@ void ProximityInfoState::refreshSpeedRates(const int inputSize, const int *const
    }
}

static const int MAX_PERCENTILE = 100;
void ProximityInfoState::refreshBeelineSpeedRates(const int inputSize,
        const int *const xCoordinates, const int *const yCoordinates, const int * times) {
    mBeelineSpeedRates.resize(mSampledInputSize);
    if (DEBUG_SAMPLING_POINTS){
        AKLOGI("--- refresh beeline speed rates");
    }
    mBeelineSpeedPercentiles.resize(mSampledInputSize);
    for (int i = 0; i < mSampledInputSize; ++i) {
        mBeelineSpeedRates[i] = calculateBeelineSpeedRate(
                i, inputSize, xCoordinates, yCoordinates, times);
        mBeelineSpeedPercentiles[i] = static_cast<int>(calculateBeelineSpeedRate(
                i, inputSize, xCoordinates, yCoordinates, times) * MAX_PERCENTILE);
    }
}

float ProximityInfoState::calculateBeelineSpeedRate(
        const int id, const int inputSize, const int *const xCoordinates,
        const int *const yCoordinates, const int * times) const {
    static const int MAX_PERCENTILE = 100;
    static const int LOOKUP_TIME_PERCENTILE = 30;
    static const int LOOKUP_RADIUS_PERCENTILE = 50;
    if (mSampledInputSize <= 0 || mAverageSpeed < 0.1f) {
    if (mSampledInputSize <= 0 || mAverageSpeed < 0.001f) {
        if (DEBUG_SAMPLING_POINTS){
            AKLOGI("--- invalid state: cancel. size = %d, ave = %f",
                    mSampledInputSize, mAverageSpeed);
        }
        return 1.0f;
    }
    const int lookupRadius =
            mProximityInfo->getMostCommonKeyWidth() * LOOKUP_RADIUS_PERCENTILE / MAX_PERCENTILE;
    const int x0 = mSampledInputXs[id];
    const int y0 = mSampledInputYs[id];
    const int lookupTime =
            (mTimes.back() - mTimes.front()) * LOOKUP_TIME_PERCENTILE / MAX_PERCENTILE;
    if (lookupTime <= 0) {
        return 1.0f;
    }
    const int actualInputIndex = mInputIndice[id];
    int tempTime = 0;
    int tempBeelineDistance = 0;
    int start = mInputIndice[id];
    int start = actualInputIndex;
    // lookup forward
    while (start > 0 && tempTime < lookupTime && tempBeelineDistance < lookupRadius) {
    while (start > 0 && tempBeelineDistance < lookupRadius) {
        tempTime += times[start] - times[start - 1];
        --start;
        tempBeelineDistance = getDistanceInt(x0, y0, xCoordinates[start], yCoordinates[start]);
    }
    // Exclusive unless this is an edge point
    if (start > 0 && start < actualInputIndex) {
        ++start;
    }
    tempTime= 0;
    tempBeelineDistance = 0;
    int end = mInputIndice[id];
    int end = actualInputIndex;
    // lookup backward
    while (end < static_cast<int>(inputSize - 1) && tempTime < lookupTime
            && tempBeelineDistance < lookupRadius) {
    while (end < (inputSize - 1) && tempBeelineDistance < lookupRadius) {
        tempTime += times[end + 1] - times[end];
        ++end;
        tempBeelineDistance = getDistanceInt(x0, y0, xCoordinates[start], yCoordinates[start]);
        tempBeelineDistance = getDistanceInt(x0, y0, xCoordinates[end], yCoordinates[end]);
    }
    // Exclusive unless this is an edge point
    if (end > actualInputIndex && end < (inputSize - 1)) {
        --end;
    }

    if (start == end) {
    if (start >= end) {
        if (DEBUG_DOUBLE_LETTER) {
            AKLOGI("--- double letter: start == end %d", start);
        }
        return 1.0f;
    }

@@ -422,11 +437,33 @@ float ProximityInfoState::calculateBeelineSpeedRate(
    const int x3 = xCoordinates[end];
    const int y3 = yCoordinates[end];
    const int beelineDistance = getDistanceInt(x2, y2, x3, y3);
    const int time = times[end] - times[start];
    int adjustedStartTime = times[start];
    if (start == 0 && actualInputIndex == 0 && inputSize > 1) {
        adjustedStartTime += FIRST_POINT_TIME_OFFSET_MILLIS;
    }
    int adjustedEndTime = times[end];
    if (end == (inputSize - 1) && inputSize > 1) {
        adjustedEndTime -= FIRST_POINT_TIME_OFFSET_MILLIS;
    }
    const int time = adjustedEndTime - adjustedStartTime;
    if (time <= 0) {
        return 1.0f;
    }
    return (static_cast<float>(beelineDistance) / static_cast<float>(time)) / mAverageSpeed;

    if (time >= STRONG_DOUBLE_LETTER_TIME_MILLIS){
        return 0.0f;
    }
    if (DEBUG_DOUBLE_LETTER) {
        AKLOGI("--- (%d, %d) double letter: start = %d, end = %d, dist = %d, time = %d, speed = %f,"
                " ave = %f, val = %f, start time = %d, end time = %d",
                id, mInputIndice[id], start, end, beelineDistance, time,
                (static_cast<float>(beelineDistance) / static_cast<float>(time)), mAverageSpeed,
                ((static_cast<float>(beelineDistance) / static_cast<float>(time)) / mAverageSpeed),
                adjustedStartTime, adjustedEndTime);
    }
    // Offset 1%
    // TODO: Detect double letter more smartly
    return 0.01f + static_cast<float>(beelineDistance) / static_cast<float>(time) / mAverageSpeed;
}

bool ProximityInfoState::checkAndReturnIsContinuationPossible(const int inputSize,
+20 −5
Original line number Diff line number Diff line
@@ -39,6 +39,10 @@ class ProximityInfoState {
    static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR;
    static const float NOT_A_DISTANCE_FLOAT;
    static const int NOT_A_CODE;
    static const int LOOKUP_RADIUS_PERCENTILE;
    static const int FIRST_POINT_TIME_OFFSET_MILLIS;
    static const int STRONG_DOUBLE_LETTER_TIME_MILLIS;
    static const int MIN_DOUBLE_LETTER_BEELINE_SPEED_PERCENTILE;

    /////////////////////////////////////////
    // Defined in proximity_info_state.cpp //
@@ -56,8 +60,8 @@ class ProximityInfoState {
              mHasTouchPositionCorrectionData(false), mMostCommonKeyWidthSquare(0), mLocaleStr(),
              mKeyCount(0), mCellHeight(0), mCellWidth(0), mGridHeight(0), mGridWidth(0),
              mIsContinuationPossible(false), mSampledInputXs(), mSampledInputYs(), mTimes(),
              mInputIndice(), mLengthCache(), mDistanceCache(), mSpeedRates(),
              mDirections(), mBeelineSpeedRates(), mCharProbabilities(), mNearKeysVector(),
              mInputIndice(), mLengthCache(), mBeelineSpeedPercentiles(), mDistanceCache(),
              mSpeedRates(), mDirections(), mCharProbabilities(), mNearKeysVector(),
              mSearchKeysVector(), mTouchPositionCorrectionEnabled(false), mSampledInputSize(0) {
        memset(mInputCodes, 0, sizeof(mInputCodes));
        memset(mNormalizedSquaredDistances, 0, sizeof(mNormalizedSquaredDistances));
@@ -167,8 +171,19 @@ class ProximityInfoState {
        return mSpeedRates[index];
    }

    AK_FORCE_INLINE float getBeelineSpeedRate(const int id) const {
        return mBeelineSpeedRates[id];
    AK_FORCE_INLINE int getBeelineSpeedPercentile(const int id) const {
        return mBeelineSpeedPercentiles[id];
    }

    AK_FORCE_INLINE DoubleLetterLevel getDoubleLetterLevel(const int id) const {
        const int beelineSpeedRate = getBeelineSpeedPercentile(id);
        if (beelineSpeedRate == 0) {
            return A_STRONG_DOUBLE_LETTER;
        } else if (beelineSpeedRate < MIN_DOUBLE_LETTER_BEELINE_SPEED_PERCENTILE) {
            return A_DOUBLE_LETTER;
        } else {
            return NOT_A_DOUBLE_LETTER;
        }
    }

    float getDirection(const int index) const {
@@ -259,10 +274,10 @@ class ProximityInfoState {
    std::vector<int> mTimes;
    std::vector<int> mInputIndice;
    std::vector<int> mLengthCache;
    std::vector<int> mBeelineSpeedPercentiles;
    std::vector<float> mDistanceCache;
    std::vector<float> mSpeedRates;
    std::vector<float> mDirections;
    std::vector<float> mBeelineSpeedRates;
    // probabilities of skipping or mapping to a key for each point.
    std::vector<hash_map_compat<int, float> > mCharProbabilities;
    // The vector for the key code set which holds nearby keys for each sampled input point