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

Commit 13148038 authored by Cody Heiner's avatar Cody Heiner Committed by Automerger Merge Worker
Browse files

Merge "Add MotionPredictorMetricsManager API" into udc-qpr-dev am: c06230c7

parents 02afd9df c06230c7
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -26,7 +26,9 @@
#include <android-base/thread_annotations.h>
#include <android/sysprop/InputProperties.sysprop.h>
#include <input/Input.h>
#include <input/MotionPredictorMetricsManager.h>
#include <input/TfLiteMotionPredictor.h>
#include <utils/Timers.h> // for nsecs_t

namespace android {

@@ -69,6 +71,7 @@ public:
     */
    MotionPredictor(nsecs_t predictionTimestampOffsetNanos,
                    std::function<bool()> checkEnableMotionPrediction = isMotionPredictionEnabled);

    /**
     * Record the actual motion received by the view. This event will be used for calculating the
     * predictions.
@@ -77,7 +80,9 @@ public:
     * consistent with the previously recorded events.
     */
    android::base::Result<void> record(const MotionEvent& event);

    std::unique_ptr<MotionEvent> predict(nsecs_t timestamp);

    bool isPredictionAvailable(int32_t deviceId, int32_t source);

private:
@@ -88,6 +93,8 @@ private:

    std::unique_ptr<TfLiteMotionPredictorBuffers> mBuffers;
    std::optional<MotionEvent> mLastEvent;

    std::optional<MotionPredictorMetricsManager> mMetricsManager;
};

} // namespace android
+36 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 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.
 */

#include <utils/Timers.h>

namespace android {

/**
 * Class to handle computing and reporting metrics for MotionPredictor.
 *
 * Currently an empty implementation, containing only the API.
 */
class MotionPredictorMetricsManager {
public:
    // Note: the MetricsManager assumes that the input interval equals the prediction interval.
    MotionPredictorMetricsManager(nsecs_t /*predictionInterval*/, size_t /*maxNumPredictions*/) {}

    void onRecord(const MotionEvent& /*inputEvent*/) {}

    void onPredict(const MotionEvent& /*predictionEvent*/) {}
};

} // namespace android
+26 −9
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ MotionPredictor::MotionPredictor(nsecs_t predictionTimestampOffsetNanos,
android::base::Result<void> MotionPredictor::record(const MotionEvent& event) {
    if (mLastEvent && mLastEvent->getDeviceId() != event.getDeviceId()) {
        // We still have an active gesture for another device. The provided MotionEvent is not
        // consistent the previous gesture.
        // consistent with the previous gesture.
        LOG(ERROR) << "Inconsistent event stream: last event is " << *mLastEvent << ", but "
                   << __func__ << " is called with " << event;
        return android::base::Error()
@@ -83,9 +83,10 @@ android::base::Result<void> MotionPredictor::record(const MotionEvent& event) {
    // Initialise the model now that it's likely to be used.
    if (!mModel) {
        mModel = TfLiteMotionPredictorModel::create();
        LOG_ALWAYS_FATAL_IF(!mModel);
    }

    if (mBuffers == nullptr) {
    if (!mBuffers) {
        mBuffers = std::make_unique<TfLiteMotionPredictorBuffers>(mModel->inputLength());
    }

@@ -133,6 +134,15 @@ android::base::Result<void> MotionPredictor::record(const MotionEvent& event) {
        mLastEvent = MotionEvent();
    }
    mLastEvent->copyFrom(&event, /*keepHistory=*/false);

    // Pass input event to the MetricsManager.
    if (!mMetricsManager) {
        mMetricsManager =
                std::make_optional<MotionPredictorMetricsManager>(mModel->predictionInterval(),
                                                                  mModel->outputLength());
    }
    mMetricsManager->onRecord(event);

    return {};
}

@@ -174,16 +184,17 @@ std::unique_ptr<MotionEvent> MotionPredictor::predict(nsecs_t timestamp) {
    const int64_t futureTime = timestamp + mPredictionTimestampOffsetNanos;

    for (int i = 0; i < predictedR.size() && predictionTime <= futureTime; ++i) {
        const TfLiteMotionPredictorSample::Point point =
        // TODO(b/266747654): Stop predictions if confidence and/or predicted pressure are below
        // some thresholds.

        const TfLiteMotionPredictorSample::Point predictedPoint =
                convertPrediction(axisFrom, axisTo, predictedR[i], predictedPhi[i]);
        // TODO(b/266747654): Stop predictions if confidence is < some threshold.

        ALOGD_IF(isDebug(), "prediction %d: %f, %f", i, point.x, point.y);
        ALOGD_IF(isDebug(), "prediction %d: %f, %f", i, predictedPoint.x, predictedPoint.y);
        PointerCoords coords;
        coords.clear();
        coords.setAxisValue(AMOTION_EVENT_AXIS_X, point.x);
        coords.setAxisValue(AMOTION_EVENT_AXIS_Y, point.y);
        // TODO(b/266747654): Stop predictions if predicted pressure is < some threshold.
        coords.setAxisValue(AMOTION_EVENT_AXIS_X, predictedPoint.x);
        coords.setAxisValue(AMOTION_EVENT_AXIS_Y, predictedPoint.y);
        coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, predictedPressure[i]);

        predictionTime += mModel->predictionInterval();
@@ -203,11 +214,17 @@ std::unique_ptr<MotionEvent> MotionPredictor::predict(nsecs_t timestamp) {
        }

        axisFrom = axisTo;
        axisTo = point;
        axisTo = predictedPoint;
    }

    if (!hasPredictions) {
        return nullptr;
    }

    // Pass predictions to the MetricsManager.
    LOG_ALWAYS_FATAL_IF(!mMetricsManager);
    mMetricsManager->onPredict(*prediction);

    return prediction;
}