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

Commit 301980e5 authored by Yeabkal Wubshit's avatar Yeabkal Wubshit Committed by Android (Google) Code Review
Browse files

Merge "Create Input SlopController"

parents 435e8ede 6b662769
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ filegroup {
        "mapper/RotaryEncoderInputMapper.cpp",
        "mapper/SensorInputMapper.cpp",
        "mapper/SingleTouchInputMapper.cpp",
        "mapper/SlopController.cpp",
        "mapper/SwitchInputMapper.cpp",
        "mapper/TouchCursorInputMapperCommon.cpp",
        "mapper/TouchInputMapper.cpp",
+12 −0
Original line number Diff line number Diff line
@@ -30,6 +30,14 @@ RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDeviceContext& deviceCon
                                                   const InputReaderConfiguration& readerConfig)
      : InputMapper(deviceContext, readerConfig), mOrientation(ui::ROTATION_0) {
    mSource = AINPUT_SOURCE_ROTARY_ENCODER;

    const PropertyMap& config = getDeviceContext().getConfiguration();
    float slopThreshold = config.getInt("rotary_encoder.slop_threshold").value_or(0);
    int32_t slopDurationMs = config.getInt("rotary_encoder.slop_duration_ms").value_or(0);
    if (slopThreshold > 0 && slopDurationMs > 0) {
        mSlopController = std::make_unique<SlopController>(slopThreshold,
                                                           (nsecs_t)(slopDurationMs * 1000000));
    }
}

RotaryEncoderInputMapper::~RotaryEncoderInputMapper() {}
@@ -103,6 +111,10 @@ std::list<NotifyArgs> RotaryEncoderInputMapper::sync(nsecs_t when, nsecs_t readT
    std::list<NotifyArgs> out;

    float scroll = mRotaryEncoderScrollAccumulator.getRelativeVWheel();
    if (mSlopController) {
        scroll = mSlopController->consumeEvent(when, scroll);
    }

    bool scrolled = scroll != 0;

    // Send motion event.
+2 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@

#include "CursorScrollAccumulator.h"
#include "InputMapper.h"
#include "SlopController.h"

namespace android {

@@ -46,6 +47,7 @@ private:
    int32_t mSource;
    float mScalingFactor;
    ui::Rotation mOrientation;
    std::unique_ptr<SlopController> mSlopController = nullptr;

    explicit RotaryEncoderInputMapper(InputDeviceContext& deviceContext,
                                      const InputReaderConfiguration& readerConfig);
+81 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 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.
 */

// clang-format off
#include "../Macros.h"
// clang-format on

#include "SlopController.h"

namespace {
int signOf(float value) {
    if (value == 0) return 0;
    if (value > 0) return 1;
    return -1;
}
} // namespace

namespace android {

SlopController::SlopController(float slopThreshold, nsecs_t slopDurationNanos)
      : mSlopThreshold(slopThreshold), mSlopDurationNanos(slopDurationNanos) {}

SlopController::~SlopController() {}

float SlopController::consumeEvent(nsecs_t eventTimeNanos, float value) {
    if (mSlopDurationNanos == 0) {
        return value;
    }

    if (shouldResetSlopTracking(eventTimeNanos, value)) {
        mCumulativeValue = 0;
        mHasSlopBeenMet = false;
    }

    mLastEventTimeNanos = eventTimeNanos;

    if (mHasSlopBeenMet) {
        // Since slop has already been met, we know that all of the current value would pass the
        // slop threshold. So return that, without any further processing.
        return value;
    }

    mCumulativeValue += value;

    if (abs(mCumulativeValue) >= mSlopThreshold) {
        mHasSlopBeenMet = true;
        // Return the amount of value that exceeds the slop.
        return signOf(value) * (abs(mCumulativeValue) - mSlopThreshold);
    }

    return 0;
}

bool SlopController::shouldResetSlopTracking(nsecs_t eventTimeNanos, float value) {
    const nsecs_t ageNanos = eventTimeNanos - mLastEventTimeNanos;
    if (ageNanos >= mSlopDurationNanos) {
        return true;
    }
    if (value == 0) {
        return false;
    }
    if (signOf(mCumulativeValue) != signOf(value)) {
        return true;
    }
    return false;
}

} // namespace android
+55 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 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.
 */

#pragma once

#include <utils/Timers.h>

namespace android {

/**
 * Controls a slop logic. Slop here refers to an approach to try and drop insignificant input
 * events. This is helpful in cases where unintentional input events may cause unintended outcomes,
 * like scrolling a screen or keeping the screen awake.
 *
 * Current slop logic:
 *      "If time since last event > Xns, then discard the next N values."
 */
class SlopController {
public:
    SlopController(float slopThreshold, nsecs_t slopDurationNanos);
    virtual ~SlopController();

    /**
     * Consumes an event with a given time and value for slop processing.
     * Returns an amount <=value that should be consumed.
     */
    float consumeEvent(nsecs_t eventTime, float value);

private:
    bool shouldResetSlopTracking(nsecs_t eventTimeNanos, float value);

    /** The amount of event values ignored after an inactivity of the slop duration. */
    const float mSlopThreshold;
    /** The duration of inactivity that resets slop controlling. */
    const nsecs_t mSlopDurationNanos;

    nsecs_t mLastEventTimeNanos = 0;
    float mCumulativeValue = 0;
    bool mHasSlopBeenMet = false;
};

} // namespace android
Loading