summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/Scheduler/LayerHistory.h
blob: 228b8a06afb4381d88fa226acd67a6b2d93e0f87 (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
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
 * 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 <android-base/thread_annotations.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>

#include <memory>
#include <mutex>
#include <utility>
#include <vector>

#include "RefreshRateConfigs.h"

namespace android {

class Layer;
class TestableScheduler;

namespace scheduler {

class LayerHistoryTest;
class LayerHistoryTestV2;
class LayerInfo;
class LayerInfoV2;

class LayerHistory {
public:
    using LayerVoteType = RefreshRateConfigs::LayerVoteType;

    virtual ~LayerHistory() = default;

    // Layers are unregistered when the weak reference expires.
    virtual void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate,
                               LayerVoteType type) = 0;

    // Sets the display size. Client is responsible for synchronization.
    virtual void setDisplayArea(uint32_t displayArea) = 0;

    // Sets whether a config change is pending to be applied
    virtual void setConfigChangePending(bool pending) = 0;

    // Represents which layer activity is recorded
    enum class LayerUpdateType {
        Buffer,       // a new buffer queued
        AnimationTX,  // a new transaction with eAnimation flag set
        SetFrameRate, // setFrameRate API was called
    };

    // Marks the layer as active, and records the given state to its history.
    virtual void record(Layer*, nsecs_t presentTime, nsecs_t now, LayerUpdateType updateType) = 0;

    using Summary = std::vector<RefreshRateConfigs::LayerRequirement>;

    // Rebuilds sets of active/inactive layers, and accumulates stats for active layers.
    virtual Summary summarize(nsecs_t now) = 0;

    virtual void clear() = 0;
};

namespace impl {
// Records per-layer history of scheduling-related information (primarily present time),
// heuristically categorizes layers as active or inactive, and summarizes stats about
// active layers (primarily maximum refresh rate). See go/content-fps-detection-in-scheduler.
class LayerHistory : public android::scheduler::LayerHistory {
public:
    LayerHistory();
    virtual ~LayerHistory();

    // Layers are unregistered when the weak reference expires.
    void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate,
                       LayerVoteType type) override;

    void setDisplayArea(uint32_t /*displayArea*/) override {}

    void setConfigChangePending(bool /*pending*/) override {}

    // Marks the layer as active, and records the given state to its history.
    void record(Layer*, nsecs_t presentTime, nsecs_t now, LayerUpdateType updateType) override;

    // Rebuilds sets of active/inactive layers, and accumulates stats for active layers.
    android::scheduler::LayerHistory::Summary summarize(nsecs_t now) override;

    void clear() override;

private:
    friend class android::scheduler::LayerHistoryTest;
    friend TestableScheduler;

    using LayerPair = std::pair<wp<Layer>, std::unique_ptr<LayerInfo>>;
    using LayerInfos = std::vector<LayerPair>;

    struct ActiveLayers {
        LayerInfos& infos;
        const size_t index;

        auto begin() { return infos.begin(); }
        auto end() { return begin() + static_cast<long>(index); }
    };

    ActiveLayers activeLayers() REQUIRES(mLock) { return {mLayerInfos, mActiveLayersEnd}; }

    // Iterates over layers in a single pass, swapping pairs such that active layers precede
    // inactive layers, and inactive layers precede expired layers. Removes expired layers by
    // truncating after inactive layers.
    void partitionLayers(nsecs_t now) REQUIRES(mLock);

    mutable std::mutex mLock;

    // Partitioned such that active layers precede inactive layers. For fast lookup, the few active
    // layers are at the front, and weak pointers are stored in contiguous memory to hit the cache.
    LayerInfos mLayerInfos GUARDED_BY(mLock);
    size_t mActiveLayersEnd GUARDED_BY(mLock) = 0;

    // Whether to emit systrace output and debug logs.
    const bool mTraceEnabled;

    // Whether to use priority sent from WindowManager to determine the relevancy of the layer.
    const bool mUseFrameRatePriority;
};

class LayerHistoryV2 : public android::scheduler::LayerHistory {
public:
    LayerHistoryV2(const scheduler::RefreshRateConfigs&);
    virtual ~LayerHistoryV2();

    // Layers are unregistered when the weak reference expires.
    void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate,
                       LayerVoteType type) override;

    // Sets the display size. Client is responsible for synchronization.
    void setDisplayArea(uint32_t displayArea) override { mDisplayArea = displayArea; }

    void setConfigChangePending(bool pending) override { mConfigChangePending = pending; }

    // Marks the layer as active, and records the given state to its history.
    void record(Layer*, nsecs_t presentTime, nsecs_t now, LayerUpdateType updateType) override;

    // Rebuilds sets of active/inactive layers, and accumulates stats for active layers.
    android::scheduler::LayerHistory::Summary summarize(nsecs_t /*now*/) override;

    void clear() override;

private:
    friend android::scheduler::LayerHistoryTestV2;
    friend TestableScheduler;

    using LayerPair = std::pair<wp<Layer>, std::unique_ptr<LayerInfoV2>>;
    using LayerInfos = std::vector<LayerPair>;

    struct ActiveLayers {
        LayerInfos& infos;
        const size_t index;

        auto begin() { return infos.begin(); }
        auto end() { return begin() + static_cast<long>(index); }
    };

    ActiveLayers activeLayers() REQUIRES(mLock) { return {mLayerInfos, mActiveLayersEnd}; }

    // Iterates over layers in a single pass, swapping pairs such that active layers precede
    // inactive layers, and inactive layers precede expired layers. Removes expired layers by
    // truncating after inactive layers.
    void partitionLayers(nsecs_t now) REQUIRES(mLock);

    mutable std::mutex mLock;

    // Partitioned such that active layers precede inactive layers. For fast lookup, the few active
    // layers are at the front, and weak pointers are stored in contiguous memory to hit the cache.
    LayerInfos mLayerInfos GUARDED_BY(mLock);
    size_t mActiveLayersEnd GUARDED_BY(mLock) = 0;

    uint32_t mDisplayArea = 0;

    // Whether to emit systrace output and debug logs.
    const bool mTraceEnabled;

    // Whether to use priority sent from WindowManager to determine the relevancy of the layer.
    const bool mUseFrameRatePriority;

    // Whether a config change is in progress or not
    std::atomic<bool> mConfigChangePending = false;
};

} // namespace impl
} // namespace scheduler
} // namespace android