File: TimeStats.h

package info (click to toggle)
android-platform-frameworks-native 1%3A10.0.0%2Br36-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 25,828 kB
  • sloc: cpp: 252,025; xml: 52,812; ansic: 26,775; java: 5,107; python: 1,887; sh: 266; asm: 105; makefile: 23
file content (168 lines) | stat: -rw-r--r-- 6,343 bytes parent folder | download | duplicates (3)
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*
 * Copyright 2018 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 <timestatsproto/TimeStatsHelper.h>
#include <timestatsproto/TimeStatsProtoHeader.h>

#include <hardware/hwcomposer_defs.h>

#include <ui/FenceTime.h>

#include <utils/String16.h>
#include <utils/Vector.h>

#include <deque>
#include <mutex>
#include <optional>
#include <unordered_map>

using namespace android::surfaceflinger;

namespace android {

class TimeStats {
public:
    virtual ~TimeStats() = default;

    virtual void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) = 0;
    virtual bool isEnabled() = 0;
    virtual std::string miniDump() = 0;

    virtual void incrementTotalFrames() = 0;
    virtual void incrementMissedFrames() = 0;
    virtual void incrementClientCompositionFrames() = 0;

    virtual void setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName,
                             nsecs_t postTime) = 0;
    virtual void setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime) = 0;
    virtual void setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime) = 0;
    virtual void setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime) = 0;
    virtual void setAcquireFence(int32_t layerID, uint64_t frameNumber,
                                 const std::shared_ptr<FenceTime>& acquireFence) = 0;
    virtual void setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime) = 0;
    virtual void setPresentFence(int32_t layerID, uint64_t frameNumber,
                                 const std::shared_ptr<FenceTime>& presentFence) = 0;
    // Clean up the layer record
    virtual void onDestroy(int32_t layerID) = 0;
    // If SF skips or rejects a buffer, remove the corresponding TimeRecord.
    virtual void removeTimeRecord(int32_t layerID, uint64_t frameNumber) = 0;

    virtual void setPowerMode(int32_t powerMode) = 0;
    // Source of truth is RefrehRateStats.
    virtual void recordRefreshRate(uint32_t fps, nsecs_t duration) = 0;
    virtual void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) = 0;
};

namespace impl {

class TimeStats : public android::TimeStats {
    struct FrameTime {
        uint64_t frameNumber = 0;
        nsecs_t postTime = 0;
        nsecs_t latchTime = 0;
        nsecs_t acquireTime = 0;
        nsecs_t desiredTime = 0;
        nsecs_t presentTime = 0;
    };

    struct TimeRecord {
        bool ready = false;
        FrameTime frameTime;
        std::shared_ptr<FenceTime> acquireFence;
        std::shared_ptr<FenceTime> presentFence;
    };

    struct LayerRecord {
        std::string layerName;
        // This is the index in timeRecords, at which the timestamps for that
        // specific frame are still not fully received. This is not waiting for
        // fences to signal, but rather waiting to receive those fences/timestamps.
        int32_t waitData = -1;
        uint32_t droppedFrames = 0;
        TimeRecord prevTimeRecord;
        std::deque<TimeRecord> timeRecords;
    };

    struct PowerTime {
        int32_t powerMode = HWC_POWER_MODE_OFF;
        nsecs_t prevTime = 0;
    };

    struct GlobalRecord {
        nsecs_t prevPresentTime = 0;
        std::deque<std::shared_ptr<FenceTime>> presentFences;
    };

public:
    TimeStats() = default;

    void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) override;
    bool isEnabled() override;
    std::string miniDump() override;

    void incrementTotalFrames() override;
    void incrementMissedFrames() override;
    void incrementClientCompositionFrames() override;

    void setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName,
                     nsecs_t postTime) override;
    void setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime) override;
    void setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime) override;
    void setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime) override;
    void setAcquireFence(int32_t layerID, uint64_t frameNumber,
                         const std::shared_ptr<FenceTime>& acquireFence) override;
    void setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime) override;
    void setPresentFence(int32_t layerID, uint64_t frameNumber,
                         const std::shared_ptr<FenceTime>& presentFence) override;
    // Clean up the layer record
    void onDestroy(int32_t layerID) override;
    // If SF skips or rejects a buffer, remove the corresponding TimeRecord.
    void removeTimeRecord(int32_t layerID, uint64_t frameNumber) override;

    void setPowerMode(int32_t powerMode) override;
    // Source of truth is RefrehRateStats.
    void recordRefreshRate(uint32_t fps, nsecs_t duration) override;
    void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) override;

    static const size_t MAX_NUM_TIME_RECORDS = 64;

private:
    bool recordReadyLocked(int32_t layerID, TimeRecord* timeRecord);
    void flushAvailableRecordsToStatsLocked(int32_t layerID);
    void flushPowerTimeLocked();
    void flushAvailableGlobalRecordsToStatsLocked();

    void enable();
    void disable();
    void clear();
    void dump(bool asProto, std::optional<uint32_t> maxLayers, std::string& result);

    std::atomic<bool> mEnabled = false;
    std::mutex mMutex;
    TimeStatsHelper::TimeStatsGlobal mTimeStats;
    // Hashmap for LayerRecord with layerID as the hash key
    std::unordered_map<int32_t, LayerRecord> mTimeStatsTracker;
    PowerTime mPowerTime;
    GlobalRecord mGlobalRecord;

    static const size_t MAX_NUM_LAYER_RECORDS = 200;
};

} // namespace impl

} // namespace android