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

Commit c7cacafa authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 12616459 from 7d24e7e9 to 25Q1-release

Change-Id: I0694c33835d0ace32276a32faee430bd3c9ae19c
parents cb5e9159 7d24e7e9
Loading
Loading
Loading
Loading
+54 −0
Original line number Diff line number Diff line
/**
 * Copyright 2024 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 <chrono>

#include <input/Input.h>
#include <input/OneEuroFilter.h>

namespace android {

/**
 * Pair of OneEuroFilters that independently filter X and Y coordinates. Both filters share the same
 * constructor's parameters. The minimum cutoff frequency is the base cutoff frequency, that is, the
 * resulting cutoff frequency in the absence of signal's speed. Likewise, beta is a scaling factor
 * of the signal's speed that sets how much the signal's speed contributes to the resulting cutoff
 * frequency. The adaptive cutoff frequency criterion is f_c = f_c_min + β|̇x_filtered|
 */
class CoordinateFilter {
public:
    explicit CoordinateFilter(float minCutoffFreq, float beta);

    /**
     * Filters in place only the AXIS_X and AXIS_Y fields from coords. Each call to filter must
     * provide a timestamp strictly greater than the timestamp of the previous call. The first time
     * this method is invoked no filtering takes place. Subsequent calls do overwrite `coords` with
     * filtered data.
     *
     * @param timestamp The timestamps at which to filter. It must be greater than the one passed in
     * the previous call.
     * @param coords Coordinates to be overwritten by the corresponding filtered coordinates.
     */
    void filter(std::chrono::duration<float> timestamp, PointerCoords& coords);

private:
    OneEuroFilter mXFilter;
    OneEuroFilter mYFilter;
};

} // namespace android
 No newline at end of file
+101 −0
Original line number Diff line number Diff line
/**
 * Copyright 2024 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 <chrono>
#include <optional>

#include <input/Input.h>

namespace android {

/**
 * Low pass filter with adaptive low pass frequency based on the signal's speed. The signal's cutoff
 * frequency is determined by f_c = f_c_min + β|̇x_filtered|. Refer to
 * https://dl.acm.org/doi/10.1145/2207676.2208639 for details on how the filter works and how to
 * tune it.
 */
class OneEuroFilter {
public:
    /**
     * Default cutoff frequency of the filtered signal's speed. 1.0 Hz is the value in the filter's
     * paper.
     */
    static constexpr float kDefaultSpeedCutoffFreq = 1.0;

    OneEuroFilter() = delete;

    explicit OneEuroFilter(float minCutoffFreq, float beta,
                           float speedCutoffFreq = kDefaultSpeedCutoffFreq);

    OneEuroFilter(const OneEuroFilter&) = delete;
    OneEuroFilter& operator=(const OneEuroFilter&) = delete;
    OneEuroFilter(OneEuroFilter&&) = delete;
    OneEuroFilter& operator=(OneEuroFilter&&) = delete;

    /**
     * Returns the filtered value of rawPosition. Each call to filter must provide a timestamp
     * strictly greater than the timestamp of the previous call. The first time the method is
     * called, it returns the value of rawPosition. Any subsequent calls provide a filtered value.
     *
     * @param timestamp The timestamp at which to filter. It must be strictly greater than the one
     * provided in the previous call.
     * @param rawPosition Position to be filtered.
     */
    float filter(std::chrono::duration<float> timestamp, float rawPosition);

private:
    /**
     * Minimum cutoff frequency. This is the constant term in the adaptive cutoff frequency
     * criterion. Units are Hertz.
     */
    const float mMinCutoffFreq;

    /**
     * Slope of the cutoff frequency criterion. This is the term scaling the absolute value of the
     * filtered signal's speed. The data member is dimensionless, that is, it does not have units.
     */
    const float mBeta;

    /**
     * Cutoff frequency of the signal's speed. This is the cutoff frequency applied to the filtering
     * of the signal's speed. Units are Hertz.
     */
    const float mSpeedCutoffFreq;

    /**
     * The timestamp from the previous call. Units are seconds.
     */
    std::optional<std::chrono::duration<float>> mPrevTimestamp;

    /**
     * The raw position from the previous call.
     */
    std::optional<float> mPrevRawPosition;

    /**
     * The filtered velocity from the previous call. Units are position per second.
     */
    std::optional<float> mPrevFilteredVelocity;

    /**
     * The filtered position from the previous call.
     */
    std::optional<float> mPrevFilteredPosition;
};

} // namespace android
+41 −0
Original line number Diff line number Diff line
@@ -19,11 +19,13 @@
#include <array>
#include <chrono>
#include <iterator>
#include <map>
#include <optional>
#include <vector>

#include <android-base/logging.h>
#include <ftl/mixins.h>
#include <input/CoordinateFilter.h>
#include <input/Input.h>
#include <input/InputTransport.h>
#include <input/RingBuffer.h>
@@ -293,4 +295,43 @@ private:
    inline static void addSampleToMotionEvent(const Sample& sample, MotionEvent& motionEvent);
};

/**
 * Resampler that first applies the LegacyResampler resampling algorithm, then independently filters
 * the X and Y coordinates with a pair of One Euro filters.
 */
class FilteredLegacyResampler final : public Resampler {
public:
    /**
     * Creates a resampler, using the given minCutoffFreq and beta to instantiate its One Euro
     * filters.
     */
    explicit FilteredLegacyResampler(float minCutoffFreq, float beta);

    void resampleMotionEvent(std::chrono::nanoseconds requestedFrameTime, MotionEvent& motionEvent,
                             const InputMessage* futureMessage) override;

    std::chrono::nanoseconds getResampleLatency() const override;

private:
    LegacyResampler mResampler;

    /**
     * Minimum cutoff frequency of the value's low pass filter. Refer to OneEuroFilter class for a
     * more detailed explanation.
     */
    const float mMinCutoffFreq;

    /**
     * Scaling factor of the adaptive cutoff frequency criterion. Refer to OneEuroFilter class for a
     * more detailed explanation.
     */
    const float mBeta;

    /*
     * Note: an associative array with constant insertion and lookup times would be more efficient.
     * When this was implemented, there was no container with these properties.
     */
    std::map<int32_t /*pointerId*/, CoordinateFilter> mFilteredPointers;
};

} // namespace android
+4 −0
Original line number Diff line number Diff line
@@ -341,6 +341,10 @@ cc_library_shared {
        "libgui_aidl_headers",
    ],

    static_libs: [
        "libsurfaceflingerflags",
    ],

    afdo: true,

    lto: {
+2 −0
Original line number Diff line number Diff line
@@ -217,6 +217,7 @@ cc_library {
    ],
    srcs: [
        "AccelerationCurve.cpp",
        "CoordinateFilter.cpp",
        "Input.cpp",
        "InputConsumer.cpp",
        "InputConsumerNoResampling.cpp",
@@ -230,6 +231,7 @@ cc_library {
        "KeyLayoutMap.cpp",
        "MotionPredictor.cpp",
        "MotionPredictorMetricsManager.cpp",
        "OneEuroFilter.cpp",
        "PrintTools.cpp",
        "PropertyMap.cpp",
        "Resampler.cpp",
Loading