blob: a0c943ba72b5058009aaf3fc4939d263f4de2eca [file] [log] [blame]
Michael Wright1509a232018-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
Dan Stoza030fbc12020-02-19 15:32:01 -080017//#define LOG_NDEBUG 0
18
Ady Abrahamabce1652022-02-24 10:51:19 -080019#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
Michael Wright1509a232018-06-21 02:50:34 +010021#undef LOG_TAG
22#define LOG_TAG "PowerAdvisor"
23
Matt Buckley06f299a2021-09-24 19:43:51 +000024#include <unistd.h>
Michael Wright1509a232018-06-21 02:50:34 +010025#include <cinttypes>
Matt Buckley06f299a2021-09-24 19:43:51 +000026#include <cstdint>
27#include <optional>
Michael Wright1509a232018-06-21 02:50:34 +010028
Dan Stoza030fbc12020-02-19 15:32:01 -080029#include <android-base/properties.h>
Michael Wright1509a232018-06-21 02:50:34 +010030#include <utils/Log.h>
31#include <utils/Mutex.h>
Ady Abrahamabce1652022-02-24 10:51:19 -080032#include <utils/Trace.h>
Michael Wright1509a232018-06-21 02:50:34 +010033
Dan Stoza030fbc12020-02-19 15:32:01 -080034#include <binder/IServiceManager.h>
35
36#include "../SurfaceFlingerProperties.h"
37
Michael Wright1509a232018-06-21 02:50:34 +010038#include "PowerAdvisor.h"
Alec Mouridea1ac52021-06-23 18:12:18 -070039#include "SurfaceFlinger.h"
Michael Wright1509a232018-06-21 02:50:34 +010040
41namespace android {
42namespace Hwc2 {
43
44PowerAdvisor::~PowerAdvisor() = default;
45
46namespace impl {
47
Xiang Wang99f6f3c2023-05-22 13:12:16 -070048using aidl::android::hardware::power::Boost;
Xiang Wang99f6f3c2023-05-22 13:12:16 -070049using aidl::android::hardware::power::Mode;
50using aidl::android::hardware::power::SessionHint;
51using aidl::android::hardware::power::WorkDuration;
Matt Buckley06f299a2021-09-24 19:43:51 +000052
Michael Wright1509a232018-06-21 02:50:34 +010053PowerAdvisor::~PowerAdvisor() = default;
54
Dan Stoza030fbc12020-02-19 15:32:01 -080055namespace {
Alec Mouri29382ad2022-05-11 18:38:38 +000056std::chrono::milliseconds getUpdateTimeout() {
Dan Stoza030fbc12020-02-19 15:32:01 -080057 // Default to a timeout of 80ms if nothing else is specified
Alec Mouri29382ad2022-05-11 18:38:38 +000058 static std::chrono::milliseconds timeout =
59 std::chrono::milliseconds(sysprop::display_update_imminent_timeout_ms(80));
Dan Stoza030fbc12020-02-19 15:32:01 -080060 return timeout;
61}
62
Ady Abrahamabce1652022-02-24 10:51:19 -080063void traceExpensiveRendering(bool enabled) {
64 if (enabled) {
65 ATRACE_ASYNC_BEGIN("ExpensiveRendering", 0);
66 } else {
67 ATRACE_ASYNC_END("ExpensiveRendering", 0);
68 }
69}
70
Dan Stoza030fbc12020-02-19 15:32:01 -080071} // namespace
72
Matt Buckley0538cae2022-11-08 23:12:04 +000073PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger)
74 : mPowerHal(std::make_unique<power::PowerHalController>()), mFlinger(flinger) {
Alec Mouri29382ad2022-05-11 18:38:38 +000075 if (getUpdateTimeout() > 0ms) {
76 mScreenUpdateTimer.emplace("UpdateImminentTimer", getUpdateTimeout(),
Alec Mouric059dcf2022-05-05 23:40:07 +000077 /* resetCallback */ nullptr,
78 /* timeoutCallback */
79 [this] {
Alec Mouri29382ad2022-05-11 18:38:38 +000080 while (true) {
81 auto timeSinceLastUpdate = std::chrono::nanoseconds(
82 systemTime() - mLastScreenUpdatedTime.load());
83 if (timeSinceLastUpdate >= getUpdateTimeout()) {
84 break;
85 }
Alec Mouric059dcf2022-05-05 23:40:07 +000086 // We may try to disable expensive rendering and allow
87 // for sending DISPLAY_UPDATE_IMMINENT hints too early if
88 // we idled very shortly after updating the screen, so
89 // make sure we wait enough time.
Alec Mouri29382ad2022-05-11 18:38:38 +000090 std::this_thread::sleep_for(getUpdateTimeout() -
91 timeSinceLastUpdate);
Alec Mouric059dcf2022-05-05 23:40:07 +000092 }
93 mSendUpdateImminent.store(true);
94 mFlinger.disableExpensiveRendering();
95 });
96 }
97}
Alec Mouridea1ac52021-06-23 18:12:18 -070098
99void PowerAdvisor::init() {
100 // Defer starting the screen update timer until SurfaceFlinger finishes construction.
Alec Mouric059dcf2022-05-05 23:40:07 +0000101 if (mScreenUpdateTimer) {
102 mScreenUpdateTimer->start();
Dan Stoza030fbc12020-02-19 15:32:01 -0800103 }
104}
Michael Wright1509a232018-06-21 02:50:34 +0100105
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700106void PowerAdvisor::onBootFinished() {
107 mBootFinished.store(true);
108}
109
Peiyong Lin74ca2f42019-01-14 19:36:57 -0800110void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000111 if (!mHasExpensiveRendering) {
112 ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
113 return;
114 }
Michael Wright1509a232018-06-21 02:50:34 +0100115 if (expected) {
116 mExpensiveDisplays.insert(displayId);
117 } else {
118 mExpensiveDisplays.erase(displayId);
119 }
120
Michael Wright1509a232018-06-21 02:50:34 +0100121 const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
122 if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000123 auto ret = getPowerHal().setMode(Mode::EXPENSIVE_RENDERING, expectsExpensiveRendering);
124 if (!ret.isOk()) {
125 if (ret.isUnsupported()) {
126 mHasExpensiveRendering = false;
127 }
Michael Wright1509a232018-06-21 02:50:34 +0100128 return;
129 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800130
Michael Wright1509a232018-06-21 02:50:34 +0100131 mNotifiedExpensiveRendering = expectsExpensiveRendering;
Matt Buckley0538cae2022-11-08 23:12:04 +0000132 traceExpensiveRendering(mNotifiedExpensiveRendering);
Michael Wright1509a232018-06-21 02:50:34 +0100133 }
134}
135
jimmyshiu4e211772023-06-15 15:18:38 +0000136void PowerAdvisor::notifyCpuLoadUp() {
137 // Only start sending this notification once the system has booted so we don't introduce an
138 // early-boot dependency on Power HAL
139 if (!mBootFinished.load()) {
140 return;
141 }
Matt Buckley547cc0c2023-10-27 22:22:36 +0000142 if (usePowerHintSession()) {
jimmyshiu4e211772023-06-15 15:18:38 +0000143 std::lock_guard lock(mHintSessionMutex);
Matt Buckley547cc0c2023-10-27 22:22:36 +0000144 if (ensurePowerHintSessionRunning()) {
145 auto ret = mHintSession->sendHint(SessionHint::CPU_LOAD_UP);
146 if (!ret.isOk()) {
147 mHintSession = nullptr;
148 }
jimmyshiu4e211772023-06-15 15:18:38 +0000149 }
150 }
151}
152
Matt Buckley15ecd1c2022-11-01 21:57:16 +0000153void PowerAdvisor::notifyDisplayUpdateImminentAndCpuReset() {
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700154 // Only start sending this notification once the system has booted so we don't introduce an
155 // early-boot dependency on Power HAL
156 if (!mBootFinished.load()) {
157 return;
158 }
159
Alec Mouric059dcf2022-05-05 23:40:07 +0000160 if (mSendUpdateImminent.exchange(false)) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000161 ALOGV("AIDL notifyDisplayUpdateImminentAndCpuReset");
Matt Buckley547cc0c2023-10-27 22:22:36 +0000162 if (usePowerHintSession()) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000163 std::lock_guard lock(mHintSessionMutex);
Matt Buckley547cc0c2023-10-27 22:22:36 +0000164 if (ensurePowerHintSessionRunning()) {
165 auto ret = mHintSession->sendHint(SessionHint::CPU_LOAD_RESET);
166 if (!ret.isOk()) {
167 mHintSession = nullptr;
168 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000169 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800170 }
171
Matt Buckley0538cae2022-11-08 23:12:04 +0000172 if (!mHasDisplayUpdateImminent) {
173 ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
174 } else {
175 auto ret = getPowerHal().setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
176 if (ret.isUnsupported()) {
177 mHasDisplayUpdateImminent = false;
178 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800179 }
Alec Mouric059dcf2022-05-05 23:40:07 +0000180
181 if (mScreenUpdateTimer) {
182 mScreenUpdateTimer->reset();
183 } else {
184 // If we don't have a screen update timer, then we don't throttle power hal calls so
185 // flip this bit back to allow for calling into power hal again.
186 mSendUpdateImminent.store(true);
187 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800188 }
189
Alec Mouric059dcf2022-05-05 23:40:07 +0000190 if (mScreenUpdateTimer) {
191 mLastScreenUpdatedTime.store(systemTime());
Dan Stoza030fbc12020-02-19 15:32:01 -0800192 }
193}
194
Matt Buckley06f299a2021-09-24 19:43:51 +0000195bool PowerAdvisor::usePowerHintSession() {
196 // uses cached value since the underlying support and flag are unlikely to change at runtime
Matt Buckley0538cae2022-11-08 23:12:04 +0000197 return mHintSessionEnabled.value_or(false) && supportsPowerHintSession();
Matt Buckley06f299a2021-09-24 19:43:51 +0000198}
199
200bool PowerAdvisor::supportsPowerHintSession() {
Matt Buckley0538cae2022-11-08 23:12:04 +0000201 if (!mSupportsHintSession.has_value()) {
202 mSupportsHintSession = getPowerHal().getHintSessionPreferredRate().isOk();
Matt Buckley06f299a2021-09-24 19:43:51 +0000203 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000204 return *mSupportsHintSession;
Matt Buckley06f299a2021-09-24 19:43:51 +0000205}
206
Matt Buckley0538cae2022-11-08 23:12:04 +0000207bool PowerAdvisor::ensurePowerHintSessionRunning() {
Matt Buckley547cc0c2023-10-27 22:22:36 +0000208 if (mHintSession == nullptr && !mHintSessionThreadIds.empty() && usePowerHintSession()) {
Peter Kalauskas48cca922024-02-08 18:24:51 +0000209 auto ret = getPowerHal().createHintSession(getpid(), static_cast<int32_t>(getuid()),
210 mHintSessionThreadIds, mTargetDuration.ns());
211
Matt Buckley547cc0c2023-10-27 22:22:36 +0000212 if (ret.isOk()) {
213 mHintSession = ret.value();
214 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000215 }
Matt Buckley547cc0c2023-10-27 22:22:36 +0000216 return mHintSession != nullptr;
Matt Buckley06f299a2021-09-24 19:43:51 +0000217}
218
Matt Buckley0538cae2022-11-08 23:12:04 +0000219void PowerAdvisor::updateTargetWorkDuration(Duration targetDuration) {
Matt Buckleyef51fba2021-10-12 19:30:12 +0000220 if (!usePowerHintSession()) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000221 ALOGV("Power hint session target duration cannot be set, skipping");
222 return;
223 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000224 ATRACE_CALL();
Matt Buckley06f299a2021-09-24 19:43:51 +0000225 {
Matt Buckley0538cae2022-11-08 23:12:04 +0000226 mTargetDuration = targetDuration;
227 if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration.ns());
Matt Buckley547cc0c2023-10-27 22:22:36 +0000228 if (targetDuration == mLastTargetDurationSent) return;
229 std::lock_guard lock(mHintSessionMutex);
230 if (ensurePowerHintSessionRunning()) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000231 ALOGV("Sending target time: %" PRId64 "ns", targetDuration.ns());
232 mLastTargetDurationSent = targetDuration;
Matt Buckley0538cae2022-11-08 23:12:04 +0000233 auto ret = mHintSession->updateTargetWorkDuration(targetDuration.ns());
234 if (!ret.isOk()) {
235 ALOGW("Failed to set power hint target work duration with error: %s",
Xiang Wang99f6f3c2023-05-22 13:12:16 -0700236 ret.getDescription().c_str());
Matt Buckley547cc0c2023-10-27 22:22:36 +0000237 mHintSession = nullptr;
Matt Buckley0538cae2022-11-08 23:12:04 +0000238 }
Matt Buckley06f299a2021-09-24 19:43:51 +0000239 }
240 }
241}
242
Matt Buckley0538cae2022-11-08 23:12:04 +0000243void PowerAdvisor::reportActualWorkDuration() {
Matt Buckley676e4392023-05-25 22:09:26 +0000244 if (!mBootFinished || !sUseReportActualDuration || !usePowerHintSession()) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000245 ALOGV("Actual work duration power hint cannot be sent, skipping");
246 return;
247 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000248 ATRACE_CALL();
249 std::optional<Duration> actualDuration = estimateWorkDuration();
Matt Buckley547cc0c2023-10-27 22:22:36 +0000250 if (!actualDuration.has_value() || actualDuration < 0ns) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000251 ALOGV("Failed to send actual work duration, skipping");
Matt Buckley50c44062022-01-17 20:48:10 +0000252 return;
253 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000254 actualDuration = std::make_optional(*actualDuration + sTargetSafetyMargin);
255 mActualDuration = actualDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000256
Matt Buckley0538cae2022-11-08 23:12:04 +0000257 if (sTraceHintSessionData) {
258 ATRACE_INT64("Measured duration", actualDuration->ns());
259 ATRACE_INT64("Target error term", Duration{*actualDuration - mTargetDuration}.ns());
260 ATRACE_INT64("Reported duration", actualDuration->ns());
261 ATRACE_INT64("Reported target", mLastTargetDurationSent.ns());
262 ATRACE_INT64("Reported target error term",
263 Duration{*actualDuration - mLastTargetDurationSent}.ns());
264 }
265
266 ALOGV("Sending actual work duration of: %" PRId64 " on reported target: %" PRId64
267 " with error: %" PRId64,
268 actualDuration->ns(), mLastTargetDurationSent.ns(),
269 Duration{*actualDuration - mLastTargetDurationSent}.ns());
270
Matt Buckley547cc0c2023-10-27 22:22:36 +0000271 if (mTimingTestingMode) {
272 mDelayReportActualMutexAcquisitonPromise.get_future().wait();
273 mDelayReportActualMutexAcquisitonPromise = std::promise<bool>{};
274 }
275
Matt Buckley0538cae2022-11-08 23:12:04 +0000276 {
277 std::lock_guard lock(mHintSessionMutex);
Matt Buckley547cc0c2023-10-27 22:22:36 +0000278 if (!ensurePowerHintSessionRunning()) {
279 ALOGV("Hint session not running and could not be started, skipping");
280 return;
281 }
282
283 WorkDuration duration{
284 .timeStampNanos = TimePoint::now().ns(),
285 // TODO(b/284324521): Correctly calculate total duration.
286 .durationNanos = actualDuration->ns(),
287 .workPeriodStartTimestampNanos = mCommitStartTimes[0].ns(),
288 .cpuDurationNanos = actualDuration->ns(),
289 // TODO(b/284324521): Calculate RenderEngine GPU time.
290 .gpuDurationNanos = 0,
291 };
292 mHintSessionQueue.push_back(duration);
293
Matt Buckley0538cae2022-11-08 23:12:04 +0000294 auto ret = mHintSession->reportActualWorkDuration(mHintSessionQueue);
295 if (!ret.isOk()) {
296 ALOGW("Failed to report actual work durations with error: %s",
Xiang Wang99f6f3c2023-05-22 13:12:16 -0700297 ret.getDescription().c_str());
Matt Buckley547cc0c2023-10-27 22:22:36 +0000298 mHintSession = nullptr;
Matt Buckley0538cae2022-11-08 23:12:04 +0000299 return;
Matt Buckley50c44062022-01-17 20:48:10 +0000300 }
301 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000302 mHintSessionQueue.clear();
Matt Buckley50c44062022-01-17 20:48:10 +0000303}
304
Matt Buckley0538cae2022-11-08 23:12:04 +0000305void PowerAdvisor::enablePowerHintSession(bool enabled) {
306 mHintSessionEnabled = enabled;
Matt Buckley06f299a2021-09-24 19:43:51 +0000307}
308
Matt Buckley547cc0c2023-10-27 22:22:36 +0000309bool PowerAdvisor::startPowerHintSession(std::vector<int32_t>&& threadIds) {
310 mHintSessionThreadIds = threadIds;
Matt Buckley0538cae2022-11-08 23:12:04 +0000311 if (!mBootFinished.load()) {
312 return false;
Matt Buckleyef51fba2021-10-12 19:30:12 +0000313 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000314 if (!usePowerHintSession()) {
315 ALOGI("Cannot start power hint session: disabled or unsupported");
316 return false;
317 }
Matt Buckley547cc0c2023-10-27 22:22:36 +0000318 LOG_ALWAYS_FATAL_IF(mHintSessionThreadIds.empty(),
319 "No thread IDs provided to power hint session!");
320 std::lock_guard lock(mHintSessionMutex);
321 if (mHintSession != nullptr) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000322 ALOGE("Cannot start power hint session: already running");
323 return false;
324 }
Matt Buckley547cc0c2023-10-27 22:22:36 +0000325 return ensurePowerHintSessionRunning();
Matt Buckleyef51fba2021-10-12 19:30:12 +0000326}
327
Matt Buckley50c44062022-01-17 20:48:10 +0000328void PowerAdvisor::setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime) {
329 DisplayTimingData& displayData = mDisplayTimingData[displayId];
330 if (displayData.gpuEndFenceTime) {
331 nsecs_t signalTime = displayData.gpuEndFenceTime->getSignalTime();
332 if (signalTime != Fence::SIGNAL_TIME_INVALID && signalTime != Fence::SIGNAL_TIME_PENDING) {
333 for (auto&& [_, otherDisplayData] : mDisplayTimingData) {
334 // If the previous display started before us but ended after we should have
335 // started, then it likely delayed our start time and we must compensate for that.
336 // Displays finishing earlier should have already made their way through this call
337 // and swapped their timing into "lastValid" from "latest", so we check that here.
338 if (!otherDisplayData.lastValidGpuStartTime.has_value()) continue;
339 if ((*otherDisplayData.lastValidGpuStartTime < *displayData.gpuStartTime) &&
340 (*otherDisplayData.lastValidGpuEndTime > *displayData.gpuStartTime)) {
341 displayData.lastValidGpuStartTime = *otherDisplayData.lastValidGpuEndTime;
342 break;
343 }
344 }
345 displayData.lastValidGpuStartTime = displayData.gpuStartTime;
Matt Buckley2fa85012022-08-30 22:38:45 +0000346 displayData.lastValidGpuEndTime = TimePoint::fromNs(signalTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000347 }
348 }
349 displayData.gpuEndFenceTime = std::move(fenceTime);
Matt Buckley2fa85012022-08-30 22:38:45 +0000350 displayData.gpuStartTime = TimePoint::now();
Matt Buckley50c44062022-01-17 20:48:10 +0000351}
352
Matt Buckley2fa85012022-08-30 22:38:45 +0000353void PowerAdvisor::setHwcValidateTiming(DisplayId displayId, TimePoint validateStartTime,
354 TimePoint validateEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000355 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000356 displayData.hwcValidateStartTime = validateStartTime;
357 displayData.hwcValidateEndTime = validateEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000358}
359
Matt Buckley2fa85012022-08-30 22:38:45 +0000360void PowerAdvisor::setHwcPresentTiming(DisplayId displayId, TimePoint presentStartTime,
361 TimePoint presentEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000362 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000363 displayData.hwcPresentStartTime = presentStartTime;
364 displayData.hwcPresentEndTime = presentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000365}
366
367void PowerAdvisor::setSkippedValidate(DisplayId displayId, bool skipped) {
368 mDisplayTimingData[displayId].skippedValidate = skipped;
369}
370
371void PowerAdvisor::setRequiresClientComposition(DisplayId displayId,
372 bool requiresClientComposition) {
373 mDisplayTimingData[displayId].usedClientComposition = requiresClientComposition;
374}
375
Matt Buckley2fa85012022-08-30 22:38:45 +0000376void PowerAdvisor::setExpectedPresentTime(TimePoint expectedPresentTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000377 mExpectedPresentTimes.append(expectedPresentTime);
378}
379
Matt Buckley2fa85012022-08-30 22:38:45 +0000380void PowerAdvisor::setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) {
Matt Buckley1809d902022-08-05 06:51:43 +0000381 mLastSfPresentEndTime = presentEndTime;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700382 mLastPresentFenceTime = presentFenceTime;
383}
384
Matt Buckley2fa85012022-08-30 22:38:45 +0000385void PowerAdvisor::setFrameDelay(Duration frameDelayDuration) {
Matt Buckley50c44062022-01-17 20:48:10 +0000386 mFrameDelayDuration = frameDelayDuration;
387}
388
Matt Buckley2fa85012022-08-30 22:38:45 +0000389void PowerAdvisor::setHwcPresentDelayedTime(DisplayId displayId, TimePoint earliestFrameStartTime) {
390 mDisplayTimingData[displayId].hwcPresentDelayedTime = earliestFrameStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000391}
392
Matt Buckley2fa85012022-08-30 22:38:45 +0000393void PowerAdvisor::setCommitStart(TimePoint commitStartTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000394 mCommitStartTimes.append(commitStartTime);
395}
396
Matt Buckley2fa85012022-08-30 22:38:45 +0000397void PowerAdvisor::setCompositeEnd(TimePoint compositeEndTime) {
398 mLastPostcompDuration = compositeEndTime - mLastSfPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000399}
400
401void PowerAdvisor::setDisplays(std::vector<DisplayId>& displayIds) {
402 mDisplayIds = displayIds;
403}
404
Matt Buckley2fa85012022-08-30 22:38:45 +0000405void PowerAdvisor::setTotalFrameTargetWorkDuration(Duration targetDuration) {
Matt Buckley50c44062022-01-17 20:48:10 +0000406 mTotalFrameTargetDuration = targetDuration;
407}
408
409std::vector<DisplayId> PowerAdvisor::getOrderedDisplayIds(
Matt Buckley2fa85012022-08-30 22:38:45 +0000410 std::optional<TimePoint> DisplayTimingData::*sortBy) {
Matt Buckley50c44062022-01-17 20:48:10 +0000411 std::vector<DisplayId> sortedDisplays;
412 std::copy_if(mDisplayIds.begin(), mDisplayIds.end(), std::back_inserter(sortedDisplays),
413 [&](DisplayId id) {
414 return mDisplayTimingData.count(id) &&
415 (mDisplayTimingData[id].*sortBy).has_value();
416 });
417 std::sort(sortedDisplays.begin(), sortedDisplays.end(), [&](DisplayId idA, DisplayId idB) {
418 return *(mDisplayTimingData[idA].*sortBy) < *(mDisplayTimingData[idB].*sortBy);
419 });
420 return sortedDisplays;
421}
422
Matt Buckley0538cae2022-11-08 23:12:04 +0000423std::optional<Duration> PowerAdvisor::estimateWorkDuration() {
424 if (!mExpectedPresentTimes.isFull() || !mCommitStartTimes.isFull()) {
Matt Buckley50c44062022-01-17 20:48:10 +0000425 return std::nullopt;
426 }
427
428 // Tracks when we finish presenting to hwc
Matt Buckley0538cae2022-11-08 23:12:04 +0000429 TimePoint estimatedHwcEndTime = mCommitStartTimes[0];
Matt Buckley50c44062022-01-17 20:48:10 +0000430
431 // How long we spent this frame not doing anything, waiting for fences or vsync
Matt Buckley2fa85012022-08-30 22:38:45 +0000432 Duration idleDuration = 0ns;
Matt Buckley50c44062022-01-17 20:48:10 +0000433
434 // Most recent previous gpu end time in the current frame, probably from a prior display, used
435 // as the start time for the next gpu operation if it ran over time since it probably blocked
Matt Buckley2fa85012022-08-30 22:38:45 +0000436 std::optional<TimePoint> previousValidGpuEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000437
438 // The currently estimated gpu end time for the frame,
439 // used to accumulate gpu time as we iterate over the active displays
Matt Buckley2fa85012022-08-30 22:38:45 +0000440 std::optional<TimePoint> estimatedGpuEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000441
Matt Buckley50c44062022-01-17 20:48:10 +0000442 // The timing info for the previously calculated display, if there was one
Matt Buckley0538cae2022-11-08 23:12:04 +0000443 std::optional<DisplayTimeline> previousDisplayTiming;
Matt Buckley50c44062022-01-17 20:48:10 +0000444 std::vector<DisplayId>&& displayIds =
Matt Buckley16dec1f2022-06-07 21:46:20 +0000445 getOrderedDisplayIds(&DisplayTimingData::hwcPresentStartTime);
Matt Buckley0538cae2022-11-08 23:12:04 +0000446 DisplayTimeline displayTiming;
Matt Buckley50c44062022-01-17 20:48:10 +0000447
Matt Buckley1809d902022-08-05 06:51:43 +0000448 // Iterate over the displays that use hwc in the same order they are presented
Matt Buckley50c44062022-01-17 20:48:10 +0000449 for (DisplayId displayId : displayIds) {
450 if (mDisplayTimingData.count(displayId) == 0) {
451 continue;
452 }
453
454 auto& displayData = mDisplayTimingData.at(displayId);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700455
Matt Buckley0538cae2022-11-08 23:12:04 +0000456 displayTiming = displayData.calculateDisplayTimeline(mLastPresentFenceTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000457
Matt Buckley16dec1f2022-06-07 21:46:20 +0000458 // If this is the first display, include the duration before hwc present starts
Matt Buckley0538cae2022-11-08 23:12:04 +0000459 if (!previousDisplayTiming.has_value()) {
460 estimatedHwcEndTime += displayTiming.hwcPresentStartTime - mCommitStartTimes[0];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000461 } else { // Otherwise add the time since last display's hwc present finished
Matt Buckley0538cae2022-11-08 23:12:04 +0000462 estimatedHwcEndTime +=
463 displayTiming.hwcPresentStartTime - previousDisplayTiming->hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000464 }
465
Matt Buckley50c44062022-01-17 20:48:10 +0000466 // Update predicted present finish time with this display's present time
Matt Buckley0538cae2022-11-08 23:12:04 +0000467 estimatedHwcEndTime = displayTiming.hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000468
469 // Track how long we spent waiting for the fence, can be excluded from the timing estimate
Matt Buckley0538cae2022-11-08 23:12:04 +0000470 idleDuration += displayTiming.probablyWaitsForPresentFence
471 ? mLastPresentFenceTime - displayTiming.presentFenceWaitStartTime
Matt Buckley2fa85012022-08-30 22:38:45 +0000472 : 0ns;
Matt Buckley50c44062022-01-17 20:48:10 +0000473
474 // Track how long we spent waiting to present, can be excluded from the timing estimate
Matt Buckley0538cae2022-11-08 23:12:04 +0000475 idleDuration += displayTiming.hwcPresentDelayDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000476
477 // Estimate the reference frame's gpu timing
478 auto gpuTiming = displayData.estimateGpuTiming(previousValidGpuEndTime);
479 if (gpuTiming.has_value()) {
480 previousValidGpuEndTime = gpuTiming->startTime + gpuTiming->duration;
481
482 // Estimate the prediction frame's gpu end time from the reference frame
Matt Buckley0538cae2022-11-08 23:12:04 +0000483 estimatedGpuEndTime = std::max(displayTiming.hwcPresentStartTime,
Matt Buckley2fa85012022-08-30 22:38:45 +0000484 estimatedGpuEndTime.value_or(TimePoint{0ns})) +
Matt Buckley50c44062022-01-17 20:48:10 +0000485 gpuTiming->duration;
486 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000487 previousDisplayTiming = displayTiming;
Matt Buckley50c44062022-01-17 20:48:10 +0000488 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000489 ATRACE_INT64("Idle duration", idleDuration.ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000490
Matt Buckley0538cae2022-11-08 23:12:04 +0000491 TimePoint estimatedFlingerEndTime = mLastSfPresentEndTime;
Matt Buckley1809d902022-08-05 06:51:43 +0000492
Matt Buckley50c44062022-01-17 20:48:10 +0000493 // Don't count time spent idly waiting in the estimate as we could do more work in that time
Matt Buckley0538cae2022-11-08 23:12:04 +0000494 estimatedHwcEndTime -= idleDuration;
Matt Buckley1809d902022-08-05 06:51:43 +0000495 estimatedFlingerEndTime -= idleDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000496
497 // We finish the frame when both present and the gpu are done, so wait for the later of the two
498 // Also add the frame delay duration since the target did not move while we were delayed
Matt Buckley2fa85012022-08-30 22:38:45 +0000499 Duration totalDuration = mFrameDelayDuration +
Matt Buckley0538cae2022-11-08 23:12:04 +0000500 std::max(estimatedHwcEndTime, estimatedGpuEndTime.value_or(TimePoint{0ns})) -
Matt Buckley2fa85012022-08-30 22:38:45 +0000501 mCommitStartTimes[0];
Matt Buckley50c44062022-01-17 20:48:10 +0000502
503 // We finish SurfaceFlinger when post-composition finishes, so add that in here
Matt Buckley2fa85012022-08-30 22:38:45 +0000504 Duration flingerDuration =
Matt Buckley1809d902022-08-05 06:51:43 +0000505 estimatedFlingerEndTime + mLastPostcompDuration - mCommitStartTimes[0];
506
507 // Combine the two timings into a single normalized one
Matt Buckley2fa85012022-08-30 22:38:45 +0000508 Duration combinedDuration = combineTimingEstimates(totalDuration, flingerDuration);
Matt Buckley50c44062022-01-17 20:48:10 +0000509
510 return std::make_optional(combinedDuration);
511}
512
Matt Buckley2fa85012022-08-30 22:38:45 +0000513Duration PowerAdvisor::combineTimingEstimates(Duration totalDuration, Duration flingerDuration) {
514 Duration targetDuration{0ns};
Matt Buckley0538cae2022-11-08 23:12:04 +0000515 targetDuration = mTargetDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000516 if (!mTotalFrameTargetDuration.has_value()) return flingerDuration;
517
518 // Normalize total to the flinger target (vsync period) since that's how often we actually send
519 // hints
Matt Buckley2fa85012022-08-30 22:38:45 +0000520 Duration normalizedTotalDuration = Duration::fromNs((targetDuration.ns() * totalDuration.ns()) /
521 mTotalFrameTargetDuration->ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000522 return std::max(flingerDuration, normalizedTotalDuration);
523}
524
Matt Buckley50c44062022-01-17 20:48:10 +0000525PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimingData::calculateDisplayTimeline(
Matt Buckley2fa85012022-08-30 22:38:45 +0000526 TimePoint fenceTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000527 DisplayTimeline timeline;
Matt Buckley16dec1f2022-06-07 21:46:20 +0000528 // How long between calling hwc present and trying to wait on the fence
Matt Buckley2fa85012022-08-30 22:38:45 +0000529 const Duration fenceWaitStartDelay =
530 (skippedValidate ? kFenceWaitStartDelaySkippedValidate : kFenceWaitStartDelayValidated);
Matt Buckley50c44062022-01-17 20:48:10 +0000531
Matt Buckley16dec1f2022-06-07 21:46:20 +0000532 // Did our reference frame wait for an appropriate vsync before calling into hwc
533 const bool waitedOnHwcPresentTime = hwcPresentDelayedTime.has_value() &&
534 *hwcPresentDelayedTime > *hwcPresentStartTime &&
535 *hwcPresentDelayedTime < *hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000536
537 // Use validate start here if we skipped it because we did validate + present together
Matt Buckley16dec1f2022-06-07 21:46:20 +0000538 timeline.hwcPresentStartTime = skippedValidate ? *hwcValidateStartTime : *hwcPresentStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000539
540 // Use validate end here if we skipped it because we did validate + present together
Matt Buckley16dec1f2022-06-07 21:46:20 +0000541 timeline.hwcPresentEndTime = skippedValidate ? *hwcValidateEndTime : *hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000542
Matt Buckley16dec1f2022-06-07 21:46:20 +0000543 // How long hwc present was delayed waiting for the next appropriate vsync
544 timeline.hwcPresentDelayDuration =
Matt Buckley2fa85012022-08-30 22:38:45 +0000545 (waitedOnHwcPresentTime ? *hwcPresentDelayedTime - *hwcPresentStartTime : 0ns);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700546 // When we started waiting for the present fence after calling into hwc present
547 timeline.presentFenceWaitStartTime =
Matt Buckley16dec1f2022-06-07 21:46:20 +0000548 timeline.hwcPresentStartTime + timeline.hwcPresentDelayDuration + fenceWaitStartDelay;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700549 timeline.probablyWaitsForPresentFence = fenceTime > timeline.presentFenceWaitStartTime &&
Matt Buckley16dec1f2022-06-07 21:46:20 +0000550 fenceTime < timeline.hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000551
Matt Buckley16dec1f2022-06-07 21:46:20 +0000552 // How long we ran after we finished waiting for the fence but before hwc present finished
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700553 timeline.postPresentFenceHwcPresentDuration = timeline.hwcPresentEndTime -
554 (timeline.probablyWaitsForPresentFence ? fenceTime
555 : timeline.presentFenceWaitStartTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000556 return timeline;
557}
558
559std::optional<PowerAdvisor::GpuTimeline> PowerAdvisor::DisplayTimingData::estimateGpuTiming(
Matt Buckley2fa85012022-08-30 22:38:45 +0000560 std::optional<TimePoint> previousEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000561 if (!(usedClientComposition && lastValidGpuStartTime.has_value() && gpuEndFenceTime)) {
562 return std::nullopt;
563 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000564 const TimePoint latestGpuStartTime =
565 std::max(previousEndTime.value_or(TimePoint{0ns}), *gpuStartTime);
566 const nsecs_t gpuEndFenceSignal = gpuEndFenceTime->getSignalTime();
567 Duration gpuDuration{0ns};
568 if (gpuEndFenceSignal != Fence::SIGNAL_TIME_INVALID &&
569 gpuEndFenceSignal != Fence::SIGNAL_TIME_PENDING) {
570 const TimePoint latestGpuEndTime = TimePoint::fromNs(gpuEndFenceSignal);
571
Matt Buckley50c44062022-01-17 20:48:10 +0000572 // If we know how long the most recent gpu duration was, use that
573 gpuDuration = latestGpuEndTime - latestGpuStartTime;
574 } else if (lastValidGpuEndTime.has_value()) {
575 // If we don't have the fence data, use the most recent information we do have
576 gpuDuration = *lastValidGpuEndTime - *lastValidGpuStartTime;
Matt Buckley2fa85012022-08-30 22:38:45 +0000577 if (gpuEndFenceSignal == Fence::SIGNAL_TIME_PENDING) {
Matt Buckley50c44062022-01-17 20:48:10 +0000578 // If pending but went over the previous duration, use current time as the end
Matt Buckley2fa85012022-08-30 22:38:45 +0000579 gpuDuration = std::max(gpuDuration, Duration{TimePoint::now() - latestGpuStartTime});
Matt Buckley50c44062022-01-17 20:48:10 +0000580 }
581 }
582 return GpuTimeline{.duration = gpuDuration, .startTime = latestGpuStartTime};
583}
584
Matt Buckley0538cae2022-11-08 23:12:04 +0000585const bool PowerAdvisor::sTraceHintSessionData =
Matt Buckleyef51fba2021-10-12 19:30:12 +0000586 base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
587
Matt Buckleyac15a1b2023-02-28 06:51:28 +0000588const Duration PowerAdvisor::sTargetSafetyMargin = std::chrono::microseconds(
589 base::GetIntProperty<int64_t>("debug.sf.hint_margin_us",
590 ticks<std::micro>(PowerAdvisor::kDefaultTargetSafetyMargin)));
591
Matt Buckley676e4392023-05-25 22:09:26 +0000592const bool PowerAdvisor::sUseReportActualDuration =
593 base::GetBoolProperty(std::string("debug.adpf.use_report_actual_duration"), true);
594
Matt Buckley0538cae2022-11-08 23:12:04 +0000595power::PowerHalController& PowerAdvisor::getPowerHal() {
596 static std::once_flag halFlag;
597 std::call_once(halFlag, [this] { mPowerHal->init(); });
598 return *mPowerHal;
Michael Wright1509a232018-06-21 02:50:34 +0100599}
600
601} // namespace impl
602} // namespace Hwc2
603} // namespace android