• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <atomic>
20 #include <chrono>
21 #include <unordered_map>
22 #include <unordered_set>
23 
24 #include <ui/DisplayId.h>
25 #include <ui/FenceTime.h>
26 #include <utils/Mutex.h>
27 
28 #include <android/hardware/power/IPower.h>
29 #include <compositionengine/impl/OutputCompositionState.h>
30 #include <powermanager/PowerHalController.h>
31 #include <scheduler/Time.h>
32 #include <ui/DisplayIdentification.h>
33 #include "../Scheduler/OneShotTimer.h"
34 
35 using namespace std::chrono_literals;
36 
37 namespace android {
38 
39 class SurfaceFlinger;
40 
41 namespace Hwc2 {
42 
43 class PowerAdvisor {
44 public:
45     virtual ~PowerAdvisor();
46 
47     // Initializes resources that cannot be initialized on construction
48     virtual void init() = 0;
49     virtual void onBootFinished() = 0;
50     virtual void setExpensiveRenderingExpected(DisplayId displayId, bool expected) = 0;
51     virtual bool isUsingExpensiveRendering() = 0;
52     virtual void notifyCpuLoadUp() = 0;
53     virtual void notifyDisplayUpdateImminentAndCpuReset() = 0;
54     // Checks both if it supports and if it's enabled
55     virtual bool usePowerHintSession() = 0;
56     virtual bool supportsPowerHintSession() = 0;
57 
58     virtual bool ensurePowerHintSessionRunning() = 0;
59     // Sends a power hint that updates to the target work duration for the frame
60     virtual void updateTargetWorkDuration(Duration targetDuration) = 0;
61     // Sends a power hint for the actual known work duration at the end of the frame
62     virtual void reportActualWorkDuration() = 0;
63     // Sets whether the power hint session is enabled
64     virtual void enablePowerHintSession(bool enabled) = 0;
65     // Initializes the power hint session
66     virtual bool startPowerHintSession(const std::vector<int32_t>& threadIds) = 0;
67     // Provides PowerAdvisor with a copy of the gpu fence so it can determine the gpu end time
68     virtual void setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime) = 0;
69     // Reports the start and end times of a hwc validate call this frame for a given display
70     virtual void setHwcValidateTiming(DisplayId displayId, TimePoint validateStartTime,
71                                       TimePoint validateEndTime) = 0;
72     // Reports the start and end times of a hwc present call this frame for a given display
73     virtual void setHwcPresentTiming(DisplayId displayId, TimePoint presentStartTime,
74                                      TimePoint presentEndTime) = 0;
75     // Reports the expected time that the current frame will present to the display
76     virtual void setExpectedPresentTime(TimePoint expectedPresentTime) = 0;
77     // Reports the most recent present fence time and end time once known
78     virtual void setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) = 0;
79     // Reports whether a display used client composition this frame
80     virtual void setRequiresClientComposition(DisplayId displayId,
81                                               bool requiresClientComposition) = 0;
82     // Reports whether a given display skipped validation this frame
83     virtual void setSkippedValidate(DisplayId displayId, bool skipped) = 0;
84     // Reports when a hwc present is delayed, and the time that it will resume
85     virtual void setHwcPresentDelayedTime(DisplayId displayId,
86                                           TimePoint earliestFrameStartTime) = 0;
87     // Reports the start delay for SurfaceFlinger this frame
88     virtual void setFrameDelay(Duration frameDelayDuration) = 0;
89     // Reports the SurfaceFlinger commit start time this frame
90     virtual void setCommitStart(TimePoint commitStartTime) = 0;
91     // Reports the SurfaceFlinger composite end time this frame
92     virtual void setCompositeEnd(TimePoint compositeEndTime) = 0;
93     // Reports the list of the currently active displays
94     virtual void setDisplays(std::vector<DisplayId>& displayIds) = 0;
95     // Sets the target duration for the entire pipeline including the gpu
96     virtual void setTotalFrameTargetWorkDuration(Duration targetDuration) = 0;
97 };
98 
99 namespace impl {
100 
101 // PowerAdvisor is a wrapper around IPower HAL which takes into account the
102 // full state of the system when sending out power hints to things like the GPU.
103 class PowerAdvisor final : public Hwc2::PowerAdvisor {
104 public:
105     PowerAdvisor(SurfaceFlinger& flinger);
106     ~PowerAdvisor() override;
107 
108     void init() override;
109     void onBootFinished() override;
110     void setExpensiveRenderingExpected(DisplayId displayId, bool expected) override;
isUsingExpensiveRendering()111     bool isUsingExpensiveRendering() override { return mNotifiedExpensiveRendering; };
112     void notifyCpuLoadUp() override;
113     void notifyDisplayUpdateImminentAndCpuReset() override;
114     bool usePowerHintSession() override;
115     bool supportsPowerHintSession() override;
116     bool ensurePowerHintSessionRunning() override;
117     void updateTargetWorkDuration(Duration targetDuration) override;
118     void reportActualWorkDuration() override;
119     void enablePowerHintSession(bool enabled) override;
120     bool startPowerHintSession(const std::vector<int32_t>& threadIds) override;
121     void setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime);
122     void setHwcValidateTiming(DisplayId displayId, TimePoint validateStartTime,
123                               TimePoint validateEndTime) override;
124     void setHwcPresentTiming(DisplayId displayId, TimePoint presentStartTime,
125                              TimePoint presentEndTime) override;
126     void setSkippedValidate(DisplayId displayId, bool skipped) override;
127     void setRequiresClientComposition(DisplayId displayId, bool requiresClientComposition) override;
128     void setExpectedPresentTime(TimePoint expectedPresentTime) override;
129     void setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) override;
130     void setHwcPresentDelayedTime(DisplayId displayId, TimePoint earliestFrameStartTime) override;
131 
132     void setFrameDelay(Duration frameDelayDuration) override;
133     void setCommitStart(TimePoint commitStartTime) override;
134     void setCompositeEnd(TimePoint compositeEndTime) override;
135     void setDisplays(std::vector<DisplayId>& displayIds) override;
136     void setTotalFrameTargetWorkDuration(Duration targetDuration) override;
137 
138 private:
139     friend class PowerAdvisorTest;
140 
141     std::unique_ptr<power::PowerHalController> mPowerHal;
142     std::atomic_bool mBootFinished = false;
143 
144     std::unordered_set<DisplayId> mExpensiveDisplays;
145     bool mNotifiedExpensiveRendering = false;
146 
147     SurfaceFlinger& mFlinger;
148     std::atomic_bool mSendUpdateImminent = true;
149     std::atomic<nsecs_t> mLastScreenUpdatedTime = 0;
150     std::optional<scheduler::OneShotTimer> mScreenUpdateTimer;
151 
152     // Higher-level timing data used for estimation
153     struct DisplayTimeline {
154         // The start of hwc present, or the start of validate if it happened there instead
155         TimePoint hwcPresentStartTime;
156         // The end of hwc present or validate, whichever one actually presented
157         TimePoint hwcPresentEndTime;
158         // How long the actual hwc present was delayed after hwcPresentStartTime
159         Duration hwcPresentDelayDuration{0ns};
160         // When we think we started waiting for the present fence after calling into hwc present and
161         // after potentially waiting for the earliest present time
162         TimePoint presentFenceWaitStartTime;
163         // How long we ran after we finished waiting for the fence but before hwc present finished
164         Duration postPresentFenceHwcPresentDuration{0ns};
165         // Are we likely to have waited for the present fence during composition
166         bool probablyWaitsForPresentFence = false;
167     };
168 
169     struct GpuTimeline {
170         Duration duration{0ns};
171         TimePoint startTime;
172     };
173 
174     // Power hint session data recorded from the pipeline
175     struct DisplayTimingData {
176         std::unique_ptr<FenceTime> gpuEndFenceTime;
177         std::optional<TimePoint> gpuStartTime;
178         std::optional<TimePoint> lastValidGpuEndTime;
179         std::optional<TimePoint> lastValidGpuStartTime;
180         std::optional<TimePoint> hwcPresentStartTime;
181         std::optional<TimePoint> hwcPresentEndTime;
182         std::optional<TimePoint> hwcValidateStartTime;
183         std::optional<TimePoint> hwcValidateEndTime;
184         std::optional<TimePoint> hwcPresentDelayedTime;
185         bool usedClientComposition = false;
186         bool skippedValidate = false;
187         // Calculate high-level timing milestones from more granular display timing data
188         DisplayTimeline calculateDisplayTimeline(TimePoint fenceTime);
189         // Estimate the gpu duration for a given display from previous gpu timing data
190         std::optional<GpuTimeline> estimateGpuTiming(std::optional<TimePoint> previousEndTime);
191     };
192 
193     template <class T, size_t N>
194     class RingBuffer {
195         std::array<T, N> elements = {};
196         size_t mIndex = 0;
197         size_t numElements = 0;
198 
199     public:
append(T item)200         void append(T item) {
201             mIndex = (mIndex + 1) % N;
202             numElements = std::min(N, numElements + 1);
203             elements[mIndex] = item;
204         }
isFull()205         bool isFull() const { return numElements == N; }
206         // Allows access like [0] == current, [-1] = previous, etc..
207         T& operator[](int offset) {
208             size_t positiveOffset =
209                     static_cast<size_t>((offset % static_cast<int>(N)) + static_cast<int>(N));
210             return elements[(mIndex + positiveOffset) % N];
211         }
212     };
213 
214     // Filter and sort the display ids by a given property
215     std::vector<DisplayId> getOrderedDisplayIds(
216             std::optional<TimePoint> DisplayTimingData::*sortBy);
217     // Estimates a frame's total work duration including gpu time.
218     std::optional<Duration> estimateWorkDuration();
219     // There are two different targets and actual work durations we care about,
220     // this normalizes them together and takes the max of the two
221     Duration combineTimingEstimates(Duration totalDuration, Duration flingerDuration);
222 
223     std::unordered_map<DisplayId, DisplayTimingData> mDisplayTimingData;
224 
225     // Current frame's delay
226     Duration mFrameDelayDuration{0ns};
227     // Last frame's post-composition duration
228     Duration mLastPostcompDuration{0ns};
229     // Buffer of recent commit start times
230     RingBuffer<TimePoint, 2> mCommitStartTimes;
231     // Buffer of recent expected present times
232     RingBuffer<TimePoint, 2> mExpectedPresentTimes;
233     // Most recent present fence time, provided by SF after composition engine finishes presenting
234     TimePoint mLastPresentFenceTime;
235     // Most recent composition engine present end time, returned with the present fence from SF
236     TimePoint mLastSfPresentEndTime;
237     // Target duration for the entire pipeline including gpu
238     std::optional<Duration> mTotalFrameTargetDuration;
239     // Updated list of display IDs
240     std::vector<DisplayId> mDisplayIds;
241 
242     // Ensure powerhal connection is initialized
243     power::PowerHalController& getPowerHal();
244 
245     std::optional<bool> mHintSessionEnabled;
246     std::optional<bool> mSupportsHintSession;
247     bool mHintSessionRunning = false;
248 
249     std::mutex mHintSessionMutex;
250     sp<hardware::power::IPowerHintSession> mHintSession GUARDED_BY(mHintSessionMutex) = nullptr;
251 
252     // Initialize to true so we try to call, to check if it's supported
253     bool mHasExpensiveRendering = true;
254     bool mHasDisplayUpdateImminent = true;
255     // Queue of actual durations saved to report
256     std::vector<hardware::power::WorkDuration> mHintSessionQueue;
257     // The latest values we have received for target and actual
258     Duration mTargetDuration = kDefaultTargetDuration;
259     std::optional<Duration> mActualDuration;
260     // The list of thread ids, stored so we can restart the session from this class if needed
261     std::vector<int32_t> mHintSessionThreadIds;
262     Duration mLastTargetDurationSent = kDefaultTargetDuration;
263     // Whether we should emit ATRACE_INT data for hint sessions
264     static const bool sTraceHintSessionData;
265 
266     // Default target duration for the hint session
267     static constexpr const Duration kDefaultTargetDuration{16ms};
268 
269     // An adjustable safety margin which pads the "actual" value sent to PowerHAL,
270     // encouraging more aggressive boosting to give SurfaceFlinger a larger margin for error
271     static const Duration sTargetSafetyMargin;
272     static constexpr const Duration kDefaultTargetSafetyMargin{1ms};
273 
274     // Whether we should send reportActualWorkDuration calls
275     static const bool sUseReportActualDuration;
276 
277     // How long we expect hwc to run after the present call until it waits for the fence
278     static constexpr const Duration kFenceWaitStartDelayValidated{150us};
279     static constexpr const Duration kFenceWaitStartDelaySkippedValidate{250us};
280 };
281 
282 } // namespace impl
283 } // namespace Hwc2
284 } // namespace android
285