• 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 <ui/DisplayIdentification.h>
31 #include "../Scheduler/OneShotTimer.h"
32 
33 using namespace std::chrono_literals;
34 
35 namespace android {
36 
37 class SurfaceFlinger;
38 
39 namespace Hwc2 {
40 
41 class PowerAdvisor {
42 public:
43     virtual ~PowerAdvisor();
44 
45     // Initializes resources that cannot be initialized on construction
46     virtual void init() = 0;
47     virtual void onBootFinished() = 0;
48     virtual void setExpensiveRenderingExpected(DisplayId displayId, bool expected) = 0;
49     virtual bool isUsingExpensiveRendering() = 0;
50     virtual void notifyDisplayUpdateImminent() = 0;
51     // Checks both if it supports and if it's enabled
52     virtual bool usePowerHintSession() = 0;
53     virtual bool supportsPowerHintSession() = 0;
54     virtual bool isPowerHintSessionRunning() = 0;
55     // Sends a power hint that updates to the target work duration for the frame
56     virtual void setTargetWorkDuration(nsecs_t targetDuration) = 0;
57     // Sends a power hint for the actual known work duration at the end of the frame
58     virtual void sendActualWorkDuration() = 0;
59     // Sends a power hint for the upcoming frame predicted from previous frame timing
60     virtual void sendPredictedWorkDuration() = 0;
61     // Sets whether the power hint session is enabled
62     virtual void enablePowerHint(bool enabled) = 0;
63     // Initializes the power hint session
64     virtual bool startPowerHintSession(const std::vector<int32_t>& threadIds) = 0;
65     // Provides PowerAdvisor with a copy of the gpu fence so it can determine the gpu end time
66     virtual void setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime) = 0;
67     // Reports the start and end times of a hwc validate call this frame for a given display
68     virtual void setHwcValidateTiming(DisplayId displayId, nsecs_t validateStartTime,
69                                       nsecs_t validateEndTime) = 0;
70     // Reports the start and end times of a hwc present call this frame for a given display
71     virtual void setHwcPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
72                                      nsecs_t presentEndTime) = 0;
73     // Reports the expected time that the current frame will present to the display
74     virtual void setExpectedPresentTime(nsecs_t expectedPresentTime) = 0;
75     // Reports the most recent present fence time and end time once known
76     virtual void setSfPresentTiming(nsecs_t presentFenceTime, nsecs_t presentEndTime) = 0;
77     // Reports whether a display used client composition this frame
78     virtual void setRequiresClientComposition(DisplayId displayId,
79                                               bool requiresClientComposition) = 0;
80     // Reports whether a given display skipped validation this frame
81     virtual void setSkippedValidate(DisplayId displayId, bool skipped) = 0;
82     // Reports when a hwc present is delayed, and the time that it will resume
83     virtual void setHwcPresentDelayedTime(
84             DisplayId displayId, std::chrono::steady_clock::time_point earliestFrameStartTime) = 0;
85     // Reports the start delay for SurfaceFlinger this frame
86     virtual void setFrameDelay(nsecs_t frameDelayDuration) = 0;
87     // Reports the SurfaceFlinger commit start time this frame
88     virtual void setCommitStart(nsecs_t commitStartTime) = 0;
89     // Reports the SurfaceFlinger composite end time this frame
90     virtual void setCompositeEnd(nsecs_t compositeEndTime) = 0;
91     // Reports the list of the currently active displays
92     virtual void setDisplays(std::vector<DisplayId>& displayIds) = 0;
93     // Sets the target duration for the entire pipeline including the gpu
94     virtual void setTotalFrameTargetWorkDuration(nsecs_t targetDuration) = 0;
95 };
96 
97 namespace impl {
98 
99 // PowerAdvisor is a wrapper around IPower HAL which takes into account the
100 // full state of the system when sending out power hints to things like the GPU.
101 class PowerAdvisor final : public Hwc2::PowerAdvisor {
102 public:
103     class HalWrapper {
104     public:
105         virtual ~HalWrapper() = default;
106 
107         virtual bool setExpensiveRendering(bool enabled) = 0;
108         virtual bool notifyDisplayUpdateImminent() = 0;
109         virtual bool supportsPowerHintSession() = 0;
110         virtual bool isPowerHintSessionRunning() = 0;
111         virtual void restartPowerHintSession() = 0;
112         virtual void setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) = 0;
113         virtual bool startPowerHintSession() = 0;
114         virtual void setTargetWorkDuration(nsecs_t targetDuration) = 0;
115         virtual void sendActualWorkDuration(nsecs_t actualDuration, nsecs_t timestamp) = 0;
116         virtual bool shouldReconnectHAL() = 0;
117         virtual std::vector<int32_t> getPowerHintSessionThreadIds() = 0;
118         virtual std::optional<nsecs_t> getTargetWorkDuration() = 0;
119     };
120 
121     PowerAdvisor(SurfaceFlinger& flinger);
122     ~PowerAdvisor() override;
123 
124     void init() override;
125     void onBootFinished() override;
126     void setExpensiveRenderingExpected(DisplayId displayId, bool expected) override;
isUsingExpensiveRendering()127     bool isUsingExpensiveRendering() override { return mNotifiedExpensiveRendering; };
128     void notifyDisplayUpdateImminent() override;
129     bool usePowerHintSession() override;
130     bool supportsPowerHintSession() override;
131     bool isPowerHintSessionRunning() override;
132     void setTargetWorkDuration(nsecs_t targetDuration) override;
133     void sendActualWorkDuration() override;
134     void sendPredictedWorkDuration() override;
135     void enablePowerHint(bool enabled) override;
136     bool startPowerHintSession(const std::vector<int32_t>& threadIds) override;
137     void setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime);
138     void setHwcValidateTiming(DisplayId displayId, nsecs_t valiateStartTime,
139                               nsecs_t validateEndTime) override;
140     void setHwcPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
141                              nsecs_t presentEndTime) override;
142     void setSkippedValidate(DisplayId displayId, bool skipped) override;
143     void setRequiresClientComposition(DisplayId displayId, bool requiresClientComposition) override;
144     void setExpectedPresentTime(nsecs_t expectedPresentTime) override;
145     void setSfPresentTiming(nsecs_t presentFenceTime, nsecs_t presentEndTime) override;
146     void setHwcPresentDelayedTime(
147             DisplayId displayId,
148             std::chrono::steady_clock::time_point earliestFrameStartTime) override;
149 
150     void setFrameDelay(nsecs_t frameDelayDuration) override;
151     void setCommitStart(nsecs_t commitStartTime) override;
152     void setCompositeEnd(nsecs_t compositeEndTime) override;
153     void setDisplays(std::vector<DisplayId>& displayIds) override;
154     void setTotalFrameTargetWorkDuration(nsecs_t targetDuration) override;
155 
156 private:
157     friend class PowerAdvisorTest;
158 
159     // Tracks if powerhal exists
160     bool mHasHal = true;
161     // Holds the hal wrapper for getPowerHal
162     std::unique_ptr<HalWrapper> mHalWrapper GUARDED_BY(mPowerHalMutex) = nullptr;
163 
164     HalWrapper* getPowerHal() REQUIRES(mPowerHalMutex);
165     bool mReconnectPowerHal GUARDED_BY(mPowerHalMutex) = false;
166     std::mutex mPowerHalMutex;
167 
168     std::atomic_bool mBootFinished = false;
169 
170     std::unordered_set<DisplayId> mExpensiveDisplays;
171     bool mNotifiedExpensiveRendering = false;
172 
173     SurfaceFlinger& mFlinger;
174     std::atomic_bool mSendUpdateImminent = true;
175     std::atomic<nsecs_t> mLastScreenUpdatedTime = 0;
176     std::optional<scheduler::OneShotTimer> mScreenUpdateTimer;
177 
178     // Higher-level timing data used for estimation
179     struct DisplayTimeline {
180         // The start of hwc present, or the start of validate if it happened there instead
181         nsecs_t hwcPresentStartTime = -1;
182         // The end of hwc present or validate, whichever one actually presented
183         nsecs_t hwcPresentEndTime = -1;
184         // How long the actual hwc present was delayed after hwcPresentStartTime
185         nsecs_t hwcPresentDelayDuration = 0;
186         // When we think we started waiting for the present fence after calling into hwc present and
187         // after potentially waiting for the earliest present time
188         nsecs_t presentFenceWaitStartTime = -1;
189         // How long we ran after we finished waiting for the fence but before hwc present finished
190         nsecs_t postPresentFenceHwcPresentDuration = 0;
191         // Are we likely to have waited for the present fence during composition
192         bool probablyWaitsForPresentFence = false;
193         // Estimate one frame's timeline from that of a previous frame
194         DisplayTimeline estimateTimelineFromReference(nsecs_t fenceTime, nsecs_t displayStartTime);
195     };
196 
197     struct GpuTimeline {
198         nsecs_t duration = 0;
199         nsecs_t startTime = -1;
200     };
201 
202     // Power hint session data recorded from the pipeline
203     struct DisplayTimingData {
204         std::unique_ptr<FenceTime> gpuEndFenceTime;
205         std::optional<nsecs_t> gpuStartTime;
206         std::optional<nsecs_t> lastValidGpuEndTime;
207         std::optional<nsecs_t> lastValidGpuStartTime;
208         std::optional<nsecs_t> hwcPresentStartTime;
209         std::optional<nsecs_t> hwcPresentEndTime;
210         std::optional<nsecs_t> hwcValidateStartTime;
211         std::optional<nsecs_t> hwcValidateEndTime;
212         std::optional<nsecs_t> hwcPresentDelayedTime;
213         bool usedClientComposition = false;
214         bool skippedValidate = false;
215         // Calculate high-level timing milestones from more granular display timing data
216         DisplayTimeline calculateDisplayTimeline(nsecs_t fenceTime);
217         // Estimate the gpu duration for a given display from previous gpu timing data
218         std::optional<GpuTimeline> estimateGpuTiming(std::optional<nsecs_t> previousEnd);
219     };
220 
221     template <class T, size_t N>
222     class RingBuffer {
223         std::array<T, N> elements = {};
224         size_t mIndex = 0;
225         size_t numElements = 0;
226 
227     public:
append(T item)228         void append(T item) {
229             mIndex = (mIndex + 1) % N;
230             numElements = std::min(N, numElements + 1);
231             elements[mIndex] = item;
232         }
isFull()233         bool isFull() const { return numElements == N; }
234         // Allows access like [0] == current, [-1] = previous, etc..
235         T& operator[](int offset) {
236             size_t positiveOffset =
237                     static_cast<size_t>((offset % static_cast<int>(N)) + static_cast<int>(N));
238             return elements[(mIndex + positiveOffset) % N];
239         }
240     };
241 
242     // Filter and sort the display ids by a given property
243     std::vector<DisplayId> getOrderedDisplayIds(std::optional<nsecs_t> DisplayTimingData::*sortBy);
244     // Estimates a frame's total work duration including gpu time.
245     // Runs either at the beginning or end of a frame, using the most recent data available
246     std::optional<nsecs_t> estimateWorkDuration(bool earlyHint);
247     // There are two different targets and actual work durations we care about,
248     // this normalizes them together and takes the max of the two
249     nsecs_t combineTimingEstimates(nsecs_t totalDuration, nsecs_t flingerDuration);
250 
251     std::unordered_map<DisplayId, DisplayTimingData> mDisplayTimingData;
252 
253     // Current frame's delay
254     nsecs_t mFrameDelayDuration = 0;
255     // Last frame's post-composition duration
256     nsecs_t mLastPostcompDuration = 0;
257     // Buffer of recent commit start times
258     RingBuffer<nsecs_t, 2> mCommitStartTimes;
259     // Buffer of recent expected present times
260     RingBuffer<nsecs_t, 2> mExpectedPresentTimes;
261     // Most recent present fence time, set at the end of the frame once known
262     nsecs_t mLastPresentFenceTime = -1;
263     // Most recent present fence time, set at the end of the frame once known
264     nsecs_t mLastSfPresentEndTime = -1;
265     // Target for the entire pipeline including gpu
266     std::optional<nsecs_t> mTotalFrameTargetDuration;
267     // Updated list of display IDs
268     std::vector<DisplayId> mDisplayIds;
269 
270     std::optional<bool> mPowerHintEnabled;
271     std::optional<bool> mSupportsPowerHint;
272     bool mPowerHintSessionRunning = false;
273 
274     // An adjustable safety margin which pads the "actual" value sent to PowerHAL,
275     // encouraging more aggressive boosting to give SurfaceFlinger a larger margin for error
276     static constexpr const std::chrono::nanoseconds kTargetSafetyMargin = 1ms;
277 
278     // How long we expect hwc to run after the present call until it waits for the fence
279     static constexpr const std::chrono::nanoseconds kFenceWaitStartDelayValidated = 150us;
280     static constexpr const std::chrono::nanoseconds kFenceWaitStartDelaySkippedValidate = 250us;
281 };
282 
283 class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
284 public:
285     explicit AidlPowerHalWrapper(sp<hardware::power::IPower> powerHal);
286     ~AidlPowerHalWrapper() override;
287 
288     static std::unique_ptr<HalWrapper> connect();
289 
290     bool setExpensiveRendering(bool enabled) override;
291     bool notifyDisplayUpdateImminent() override;
292     bool supportsPowerHintSession() override;
293     bool isPowerHintSessionRunning() override;
294     void restartPowerHintSession() override;
295     void setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) override;
296     bool startPowerHintSession() override;
297     void setTargetWorkDuration(nsecs_t targetDuration) override;
298     void sendActualWorkDuration(nsecs_t actualDuration, nsecs_t timestamp) override;
299     bool shouldReconnectHAL() override;
300     std::vector<int32_t> getPowerHintSessionThreadIds() override;
301     std::optional<nsecs_t> getTargetWorkDuration() override;
302 
303 private:
304     friend class AidlPowerHalWrapperTest;
305 
306     bool checkPowerHintSessionSupported();
307     void closePowerHintSession();
308     bool shouldReportActualDurations();
309 
310     // Used for testing
311     void setAllowedActualDeviation(nsecs_t);
312 
313     const sp<hardware::power::IPower> mPowerHal = nullptr;
314     bool mHasExpensiveRendering = false;
315     bool mHasDisplayUpdateImminent = false;
316     // Used to indicate an error state and need for reconstruction
317     bool mShouldReconnectHal = false;
318 
319     // Power hint session data
320 
321     // Concurrent access for this is protected by mPowerHalMutex
322     sp<hardware::power::IPowerHintSession> mPowerHintSession = nullptr;
323     // Queue of actual durations saved to report
324     std::vector<hardware::power::WorkDuration> mPowerHintQueue;
325     // The latest values we have received for target and actual
326     nsecs_t mTargetDuration = kDefaultTarget.count();
327     std::optional<nsecs_t> mActualDuration;
328     // The list of thread ids, stored so we can restart the session from this class if needed
329     std::vector<int32_t> mPowerHintThreadIds;
330     bool mSupportsPowerHint = false;
331     // Keep track of the last messages sent for rate limiter change detection
332     std::optional<nsecs_t> mLastActualDurationSent;
333     // Timestamp of the last report we sent, used to avoid stale sessions
334     nsecs_t mLastActualReportTimestamp = 0;
335     nsecs_t mLastTargetDurationSent = kDefaultTarget.count();
336     // Max amount the error term can vary without causing an actual value report
337     nsecs_t mAllowedActualDeviation = -1;
338     // Whether we should emit ATRACE_INT data for hint sessions
339     static const bool sTraceHintSessionData;
340     static constexpr const std::chrono::nanoseconds kDefaultTarget = 16ms;
341     // Amount of time after the last message was sent before the session goes stale
342     // actually 100ms but we use 80 here to ideally avoid going stale
343     static constexpr const std::chrono::nanoseconds kStaleTimeout = 80ms;
344 };
345 
346 } // namespace impl
347 } // namespace Hwc2
348 } // namespace android
349