blob: 6e25f787d7c119ee6e0360a5ed33248a50fa1fdc [file] [log] [blame]
Michael Wright5d22d4f2018-06-21 02:50:34 +01001/*
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
Dan Stoza030fbc12020-02-19 15:32:01 -080019#include <atomic>
Matt Buckleyef51fba2021-10-12 19:30:12 +000020#include <chrono>
Matt Buckley50c44062022-01-17 20:48:10 +000021#include <unordered_map>
Peiyong Lin74ca2f42019-01-14 19:36:57 -080022#include <unordered_set>
23
Matt Buckley50c44062022-01-17 20:48:10 +000024#include <ui/DisplayId.h>
25#include <ui/FenceTime.h>
Dan Stoza20950002020-06-18 14:56:58 -070026#include <utils/Mutex.h>
27
Xiang Wange12b4fa2022-03-25 23:48:40 +000028#include <android/hardware/power/IPower.h>
Matt Buckley50c44062022-01-17 20:48:10 +000029#include <compositionengine/impl/OutputCompositionState.h>
Alec Mouriff793872022-01-13 17:45:06 -080030#include <ui/DisplayIdentification.h>
Dan Stoza030fbc12020-02-19 15:32:01 -080031#include "../Scheduler/OneShotTimer.h"
Michael Wright5d22d4f2018-06-21 02:50:34 +010032
Matt Buckleyef51fba2021-10-12 19:30:12 +000033using namespace std::chrono_literals;
34
Michael Wright5d22d4f2018-06-21 02:50:34 +010035namespace android {
Alec Mouridea1ac52021-06-23 18:12:18 -070036
37class SurfaceFlinger;
38
Michael Wright5d22d4f2018-06-21 02:50:34 +010039namespace Hwc2 {
40
41class PowerAdvisor {
42public:
43 virtual ~PowerAdvisor();
44
Alec Mouridea1ac52021-06-23 18:12:18 -070045 // Initializes resources that cannot be initialized on construction
46 virtual void init() = 0;
Dan Stoza29e7bdf2020-03-23 14:43:09 -070047 virtual void onBootFinished() = 0;
Peiyong Lin74ca2f42019-01-14 19:36:57 -080048 virtual void setExpensiveRenderingExpected(DisplayId displayId, bool expected) = 0;
Alec Mouridea1ac52021-06-23 18:12:18 -070049 virtual bool isUsingExpensiveRendering() = 0;
Dan Stoza030fbc12020-02-19 15:32:01 -080050 virtual void notifyDisplayUpdateImminent() = 0;
Matt Buckley50c44062022-01-17 20:48:10 +000051 // Checks both if it supports and if it's enabled
Matt Buckley06f299a2021-09-24 19:43:51 +000052 virtual bool usePowerHintSession() = 0;
53 virtual bool supportsPowerHintSession() = 0;
54 virtual bool isPowerHintSessionRunning() = 0;
Matt Buckley50c44062022-01-17 20:48:10 +000055 // 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
Matt Buckley06f299a2021-09-24 19:43:51 +000062 virtual void enablePowerHint(bool enabled) = 0;
Matt Buckley50c44062022-01-17 20:48:10 +000063 // Initializes the power hint session
Matt Buckleyef51fba2021-10-12 19:30:12 +000064 virtual bool startPowerHintSession(const std::vector<int32_t>& threadIds) = 0;
Matt Buckley50c44062022-01-17 20:48:10 +000065 // 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;
Matt Buckley16dec1f2022-06-07 21:46:20 +000067 // 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;
Matt Buckleyc6b9d382022-06-17 15:28:07 -070073 // Reports the expected time that the current frame will present to the display
Matt Buckley50c44062022-01-17 20:48:10 +000074 virtual void setExpectedPresentTime(nsecs_t expectedPresentTime) = 0;
Matt Buckley3e68cce2022-08-05 06:51:43 +000075 // Reports the most recent present fence time and end time once known
76 virtual void setSfPresentTiming(nsecs_t presentFenceTime, nsecs_t presentEndTime) = 0;
Matt Buckley50c44062022-01-17 20:48:10 +000077 // 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;
Matt Buckley16dec1f2022-06-07 21:46:20 +000082 // Reports when a hwc present is delayed, and the time that it will resume
83 virtual void setHwcPresentDelayedTime(
Matt Buckley50c44062022-01-17 20:48:10 +000084 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;
Michael Wright5d22d4f2018-06-21 02:50:34 +010095};
96
97namespace impl {
98
Michael Wright5d22d4f2018-06-21 02:50:34 +010099// 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.
101class PowerAdvisor final : public Hwc2::PowerAdvisor {
102public:
Dan Stoza030fbc12020-02-19 15:32:01 -0800103 class HalWrapper {
104 public:
105 virtual ~HalWrapper() = default;
106
107 virtual bool setExpensiveRendering(bool enabled) = 0;
108 virtual bool notifyDisplayUpdateImminent() = 0;
Matt Buckley06f299a2021-09-24 19:43:51 +0000109 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;
Matt Buckley50c44062022-01-17 20:48:10 +0000114 virtual void setTargetWorkDuration(nsecs_t targetDuration) = 0;
115 virtual void sendActualWorkDuration(nsecs_t actualDuration, nsecs_t timestamp) = 0;
Matt Buckley06f299a2021-09-24 19:43:51 +0000116 virtual bool shouldReconnectHAL() = 0;
117 virtual std::vector<int32_t> getPowerHintSessionThreadIds() = 0;
Matt Buckley50c44062022-01-17 20:48:10 +0000118 virtual std::optional<nsecs_t> getTargetWorkDuration() = 0;
Dan Stoza030fbc12020-02-19 15:32:01 -0800119 };
120
Alec Mouridea1ac52021-06-23 18:12:18 -0700121 PowerAdvisor(SurfaceFlinger& flinger);
Michael Wright5d22d4f2018-06-21 02:50:34 +0100122 ~PowerAdvisor() override;
123
Alec Mouridea1ac52021-06-23 18:12:18 -0700124 void init() override;
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700125 void onBootFinished() override;
Peiyong Lin74ca2f42019-01-14 19:36:57 -0800126 void setExpensiveRenderingExpected(DisplayId displayId, bool expected) override;
Matt Buckley06f299a2021-09-24 19:43:51 +0000127 bool isUsingExpensiveRendering() override { return mNotifiedExpensiveRendering; };
Dan Stoza030fbc12020-02-19 15:32:01 -0800128 void notifyDisplayUpdateImminent() override;
Matt Buckley06f299a2021-09-24 19:43:51 +0000129 bool usePowerHintSession() override;
130 bool supportsPowerHintSession() override;
131 bool isPowerHintSessionRunning() override;
Matt Buckley50c44062022-01-17 20:48:10 +0000132 void setTargetWorkDuration(nsecs_t targetDuration) override;
133 void sendActualWorkDuration() override;
134 void sendPredictedWorkDuration() override;
Matt Buckley06f299a2021-09-24 19:43:51 +0000135 void enablePowerHint(bool enabled) override;
Matt Buckleyef51fba2021-10-12 19:30:12 +0000136 bool startPowerHintSession(const std::vector<int32_t>& threadIds) override;
Matt Buckley50c44062022-01-17 20:48:10 +0000137 void setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime);
Matt Buckley16dec1f2022-06-07 21:46:20 +0000138 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;
Matt Buckley50c44062022-01-17 20:48:10 +0000142 void setSkippedValidate(DisplayId displayId, bool skipped) override;
143 void setRequiresClientComposition(DisplayId displayId, bool requiresClientComposition) override;
144 void setExpectedPresentTime(nsecs_t expectedPresentTime) override;
Matt Buckley3e68cce2022-08-05 06:51:43 +0000145 void setSfPresentTiming(nsecs_t presentFenceTime, nsecs_t presentEndTime) override;
Matt Buckley16dec1f2022-06-07 21:46:20 +0000146 void setHwcPresentDelayedTime(
Matt Buckley50c44062022-01-17 20:48:10 +0000147 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;
Michael Wright5d22d4f2018-06-21 02:50:34 +0100155
156private:
Matt Buckley57274052022-08-12 21:54:23 +0000157 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
Dan Stoza20950002020-06-18 14:56:58 -0700164 HalWrapper* getPowerHal() REQUIRES(mPowerHalMutex);
165 bool mReconnectPowerHal GUARDED_BY(mPowerHalMutex) = false;
166 std::mutex mPowerHalMutex;
Dan Stoza030fbc12020-02-19 15:32:01 -0800167
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700168 std::atomic_bool mBootFinished = false;
Matt Buckleyef51fba2021-10-12 19:30:12 +0000169
Peiyong Lin74ca2f42019-01-14 19:36:57 -0800170 std::unordered_set<DisplayId> mExpensiveDisplays;
Michael Wright5d22d4f2018-06-21 02:50:34 +0100171 bool mNotifiedExpensiveRendering = false;
Dan Stoza030fbc12020-02-19 15:32:01 -0800172
Alec Mouridea1ac52021-06-23 18:12:18 -0700173 SurfaceFlinger& mFlinger;
Dan Stoza030fbc12020-02-19 15:32:01 -0800174 std::atomic_bool mSendUpdateImminent = true;
Alec Mouric059dcf2022-05-05 23:40:07 +0000175 std::atomic<nsecs_t> mLastScreenUpdatedTime = 0;
176 std::optional<scheduler::OneShotTimer> mScreenUpdateTimer;
Matt Buckley50c44062022-01-17 20:48:10 +0000177
178 // Higher-level timing data used for estimation
179 struct DisplayTimeline {
Matt Buckley16dec1f2022-06-07 21:46:20 +0000180 // 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;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700186 // When we think we started waiting for the present fence after calling into hwc present and
Matt Buckley50c44062022-01-17 20:48:10 +0000187 // after potentially waiting for the earliest present time
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700188 nsecs_t presentFenceWaitStartTime = -1;
Matt Buckley16dec1f2022-06-07 21:46:20 +0000189 // How long we ran after we finished waiting for the fence but before hwc present finished
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700190 nsecs_t postPresentFenceHwcPresentDuration = 0;
Matt Buckley50c44062022-01-17 20:48:10 +0000191 // Are we likely to have waited for the present fence during composition
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700192 bool probablyWaitsForPresentFence = false;
Matt Buckley50c44062022-01-17 20:48:10 +0000193 // 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;
Matt Buckley16dec1f2022-06-07 21:46:20 +0000208 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;
Matt Buckley50c44062022-01-17 20:48:10 +0000213 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:
228 void append(T item) {
229 mIndex = (mIndex + 1) % N;
230 numElements = std::min(N, numElements + 1);
231 elements[mIndex] = item;
232 }
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;
Matt Buckley50c44062022-01-17 20:48:10 +0000255 // 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
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700260 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;
Matt Buckley3e68cce2022-08-05 06:51:43 +0000263 // Most recent present fence time, set at the end of the frame once known
264 nsecs_t mLastSfPresentEndTime = -1;
Matt Buckley50c44062022-01-17 20:48:10 +0000265 // 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
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700274 // 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
Matt Buckley50c44062022-01-17 20:48:10 +0000276 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
Matt Buckley16dec1f2022-06-07 21:46:20 +0000279 static constexpr const std::chrono::nanoseconds kFenceWaitStartDelayValidated = 150us;
280 static constexpr const std::chrono::nanoseconds kFenceWaitStartDelaySkippedValidate = 250us;
Michael Wright5d22d4f2018-06-21 02:50:34 +0100281};
282
Xiang Wange12b4fa2022-03-25 23:48:40 +0000283class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
284public:
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;
Matt Buckley50c44062022-01-17 20:48:10 +0000297 void setTargetWorkDuration(nsecs_t targetDuration) override;
298 void sendActualWorkDuration(nsecs_t actualDuration, nsecs_t timestamp) override;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000299 bool shouldReconnectHAL() override;
300 std::vector<int32_t> getPowerHintSessionThreadIds() override;
Matt Buckley50c44062022-01-17 20:48:10 +0000301 std::optional<nsecs_t> getTargetWorkDuration() override;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000302
303private:
Matt Buckley50c44062022-01-17 20:48:10 +0000304 friend class AidlPowerHalWrapperTest;
305
Xiang Wange12b4fa2022-03-25 23:48:40 +0000306 bool checkPowerHintSessionSupported();
307 void closePowerHintSession();
Matt Buckley50c44062022-01-17 20:48:10 +0000308 bool shouldReportActualDurations();
309
310 // Used for testing
311 void setAllowedActualDeviation(nsecs_t);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000312
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;
Matt Buckley50c44062022-01-17 20:48:10 +0000318
319 // Power hint session data
320
321 // Concurrent access for this is protected by mPowerHalMutex
Xiang Wange12b4fa2022-03-25 23:48:40 +0000322 sp<hardware::power::IPowerHintSession> mPowerHintSession = nullptr;
323 // Queue of actual durations saved to report
324 std::vector<hardware::power::WorkDuration> mPowerHintQueue;
Matt Buckley50c44062022-01-17 20:48:10 +0000325 // The latest values we have received for target and actual
326 nsecs_t mTargetDuration = kDefaultTarget.count();
327 std::optional<nsecs_t> mActualDuration;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000328 // The list of thread ids, stored so we can restart the session from this class if needed
329 std::vector<int32_t> mPowerHintThreadIds;
Matt Buckley50c44062022-01-17 20:48:10 +0000330 bool mSupportsPowerHint = false;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000331 // Keep track of the last messages sent for rate limiter change detection
Matt Buckley50c44062022-01-17 20:48:10 +0000332 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;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000338 // Whether we should emit ATRACE_INT data for hint sessions
339 static const bool sTraceHintSessionData;
Matt Buckley50c44062022-01-17 20:48:10 +0000340 static constexpr const std::chrono::nanoseconds kDefaultTarget = 16ms;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000341 // 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
Michael Wright5d22d4f2018-06-21 02:50:34 +0100346} // namespace impl
347} // namespace Hwc2
348} // namespace android