summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/Scheduler/VSyncPredictor.h
blob: 40e69443beb9165a71769ca7ab8b7d8995a753ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
 * Copyright 2019 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 <android-base/thread_annotations.h>
#include <mutex>
#include <unordered_map>
#include <vector>
#include "SchedulerUtils.h"
#include "VSyncTracker.h"

namespace android::scheduler {

class VSyncPredictor : public VSyncTracker {
public:
    /*
     * \param [in] idealPeriod  The initial ideal period to use.
     * \param [in] historySize  The internal amount of entries to store in the model.
     * \param [in] minimumSamplesForPrediction The minimum number of samples to collect before
     * predicting. \param [in] outlierTolerancePercent a number 0 to 100 that will be used to filter
     * samples that fall outlierTolerancePercent from an anticipated vsync event.
     */
    VSyncPredictor(nsecs_t idealPeriod, size_t historySize, size_t minimumSamplesForPrediction,
                   uint32_t outlierTolerancePercent);
    ~VSyncPredictor();

    bool addVsyncTimestamp(nsecs_t timestamp) final EXCLUDES(mMutex);
    nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const final EXCLUDES(mMutex);
    nsecs_t currentPeriod() const final EXCLUDES(mMutex);
    void resetModel() final EXCLUDES(mMutex);

    /*
     * Inform the model that the period is anticipated to change to a new value.
     * model will use the period parameter to predict vsync events until enough
     * timestamps with the new period have been collected.
     *
     * \param [in] period   The new period that should be used.
     */
    void setPeriod(nsecs_t period) final EXCLUDES(mMutex);

    /* Query if the model is in need of more samples to make a prediction.
     * \return  True, if model would benefit from more samples, False if not.
     */
    bool needsMoreSamples() const final EXCLUDES(mMutex);

    struct Model {
        nsecs_t slope;
        nsecs_t intercept;
    };

    VSyncPredictor::Model getVSyncPredictionModel() const EXCLUDES(mMutex);

    bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const final EXCLUDES(mMutex);

    void dump(std::string& result) const final EXCLUDES(mMutex);

private:
    VSyncPredictor(VSyncPredictor const&) = delete;
    VSyncPredictor& operator=(VSyncPredictor const&) = delete;
    void clearTimestamps() REQUIRES(mMutex);

    inline void traceInt64If(const char* name, int64_t value) const;
    bool const mTraceOn;

    size_t const kHistorySize;
    size_t const kMinimumSamplesForPrediction;
    size_t const kOutlierTolerancePercent;

    std::mutex mutable mMutex;
    size_t next(size_t i) const REQUIRES(mMutex);
    bool validate(nsecs_t timestamp) const REQUIRES(mMutex);

    Model getVSyncPredictionModelLocked() const REQUIRES(mMutex);

    nsecs_t nextAnticipatedVSyncTimeFromLocked(nsecs_t timePoint) const REQUIRES(mMutex);

    nsecs_t mIdealPeriod GUARDED_BY(mMutex);
    std::optional<nsecs_t> mKnownTimestamp GUARDED_BY(mMutex);

    // Map between ideal vsync period and the calculated model
    std::unordered_map<nsecs_t, Model> mutable mRateMap GUARDED_BY(mMutex);

    // Map between the divided vsync period and the last known vsync timestamp
    std::unordered_map<nsecs_t, nsecs_t> mutable mRateDividerKnownTimestampMap GUARDED_BY(mMutex);

    size_t mLastTimestampIndex GUARDED_BY(mMutex) = 0;
    std::vector<nsecs_t> mTimestamps GUARDED_BY(mMutex);
};

} // namespace android::scheduler