blob: 96d5ca615505f33687ac5ab243a786d27bd83ba2 [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;
Matt Buckley52dfaad2024-03-07 20:20:07 +000051using aidl::android::hardware::power::SessionTag;
Xiang Wang99f6f3c2023-05-22 13:12:16 -070052using aidl::android::hardware::power::WorkDuration;
Matt Buckley06f299a2021-09-24 19:43:51 +000053
Michael Wright1509a232018-06-21 02:50:34 +010054PowerAdvisor::~PowerAdvisor() = default;
55
Dan Stoza030fbc12020-02-19 15:32:01 -080056namespace {
Alec Mouri29382ad2022-05-11 18:38:38 +000057std::chrono::milliseconds getUpdateTimeout() {
Dan Stoza030fbc12020-02-19 15:32:01 -080058 // Default to a timeout of 80ms if nothing else is specified
Alec Mouri29382ad2022-05-11 18:38:38 +000059 static std::chrono::milliseconds timeout =
60 std::chrono::milliseconds(sysprop::display_update_imminent_timeout_ms(80));
Dan Stoza030fbc12020-02-19 15:32:01 -080061 return timeout;
62}
63
Ady Abrahamabce1652022-02-24 10:51:19 -080064void traceExpensiveRendering(bool enabled) {
65 if (enabled) {
66 ATRACE_ASYNC_BEGIN("ExpensiveRendering", 0);
67 } else {
68 ATRACE_ASYNC_END("ExpensiveRendering", 0);
69 }
70}
71
Dan Stoza030fbc12020-02-19 15:32:01 -080072} // namespace
73
Matt Buckley0538cae2022-11-08 23:12:04 +000074PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger)
75 : mPowerHal(std::make_unique<power::PowerHalController>()), mFlinger(flinger) {
Alec Mouri29382ad2022-05-11 18:38:38 +000076 if (getUpdateTimeout() > 0ms) {
77 mScreenUpdateTimer.emplace("UpdateImminentTimer", getUpdateTimeout(),
Alec Mouric059dcf2022-05-05 23:40:07 +000078 /* resetCallback */ nullptr,
79 /* timeoutCallback */
80 [this] {
Alec Mouri29382ad2022-05-11 18:38:38 +000081 while (true) {
82 auto timeSinceLastUpdate = std::chrono::nanoseconds(
83 systemTime() - mLastScreenUpdatedTime.load());
84 if (timeSinceLastUpdate >= getUpdateTimeout()) {
85 break;
86 }
Alec Mouric059dcf2022-05-05 23:40:07 +000087 // We may try to disable expensive rendering and allow
88 // for sending DISPLAY_UPDATE_IMMINENT hints too early if
89 // we idled very shortly after updating the screen, so
90 // make sure we wait enough time.
Alec Mouri29382ad2022-05-11 18:38:38 +000091 std::this_thread::sleep_for(getUpdateTimeout() -
92 timeSinceLastUpdate);
Alec Mouric059dcf2022-05-05 23:40:07 +000093 }
94 mSendUpdateImminent.store(true);
95 mFlinger.disableExpensiveRendering();
96 });
97 }
98}
Alec Mouridea1ac52021-06-23 18:12:18 -070099
100void PowerAdvisor::init() {
101 // Defer starting the screen update timer until SurfaceFlinger finishes construction.
Alec Mouric059dcf2022-05-05 23:40:07 +0000102 if (mScreenUpdateTimer) {
103 mScreenUpdateTimer->start();
Dan Stoza030fbc12020-02-19 15:32:01 -0800104 }
105}
Michael Wright1509a232018-06-21 02:50:34 +0100106
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700107void PowerAdvisor::onBootFinished() {
108 mBootFinished.store(true);
109}
110
Peiyong Lin74ca2f42019-01-14 19:36:57 -0800111void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000112 if (!mHasExpensiveRendering) {
113 ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
114 return;
115 }
Michael Wright1509a232018-06-21 02:50:34 +0100116 if (expected) {
117 mExpensiveDisplays.insert(displayId);
118 } else {
119 mExpensiveDisplays.erase(displayId);
120 }
121
Michael Wright1509a232018-06-21 02:50:34 +0100122 const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
123 if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000124 auto ret = getPowerHal().setMode(Mode::EXPENSIVE_RENDERING, expectsExpensiveRendering);
125 if (!ret.isOk()) {
126 if (ret.isUnsupported()) {
127 mHasExpensiveRendering = false;
128 }
Michael Wright1509a232018-06-21 02:50:34 +0100129 return;
130 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800131
Michael Wright1509a232018-06-21 02:50:34 +0100132 mNotifiedExpensiveRendering = expectsExpensiveRendering;
Matt Buckley0538cae2022-11-08 23:12:04 +0000133 traceExpensiveRendering(mNotifiedExpensiveRendering);
Michael Wright1509a232018-06-21 02:50:34 +0100134 }
135}
136
jimmyshiu4e211772023-06-15 15:18:38 +0000137void PowerAdvisor::notifyCpuLoadUp() {
138 // Only start sending this notification once the system has booted so we don't introduce an
139 // early-boot dependency on Power HAL
140 if (!mBootFinished.load()) {
141 return;
142 }
Matt Buckley547cc0c2023-10-27 22:22:36 +0000143 if (usePowerHintSession()) {
jimmyshiu4e211772023-06-15 15:18:38 +0000144 std::lock_guard lock(mHintSessionMutex);
Matt Buckley547cc0c2023-10-27 22:22:36 +0000145 if (ensurePowerHintSessionRunning()) {
146 auto ret = mHintSession->sendHint(SessionHint::CPU_LOAD_UP);
147 if (!ret.isOk()) {
148 mHintSession = nullptr;
149 }
jimmyshiu4e211772023-06-15 15:18:38 +0000150 }
151 }
152}
153
Matt Buckley15ecd1c2022-11-01 21:57:16 +0000154void PowerAdvisor::notifyDisplayUpdateImminentAndCpuReset() {
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700155 // Only start sending this notification once the system has booted so we don't introduce an
156 // early-boot dependency on Power HAL
157 if (!mBootFinished.load()) {
158 return;
159 }
160
Alec Mouric059dcf2022-05-05 23:40:07 +0000161 if (mSendUpdateImminent.exchange(false)) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000162 ALOGV("AIDL notifyDisplayUpdateImminentAndCpuReset");
Matt Buckley547cc0c2023-10-27 22:22:36 +0000163 if (usePowerHintSession()) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000164 std::lock_guard lock(mHintSessionMutex);
Matt Buckley547cc0c2023-10-27 22:22:36 +0000165 if (ensurePowerHintSessionRunning()) {
166 auto ret = mHintSession->sendHint(SessionHint::CPU_LOAD_RESET);
167 if (!ret.isOk()) {
168 mHintSession = nullptr;
169 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000170 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800171 }
172
Matt Buckley0538cae2022-11-08 23:12:04 +0000173 if (!mHasDisplayUpdateImminent) {
174 ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
175 } else {
176 auto ret = getPowerHal().setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
177 if (ret.isUnsupported()) {
178 mHasDisplayUpdateImminent = false;
179 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800180 }
Alec Mouric059dcf2022-05-05 23:40:07 +0000181
182 if (mScreenUpdateTimer) {
183 mScreenUpdateTimer->reset();
184 } else {
185 // If we don't have a screen update timer, then we don't throttle power hal calls so
186 // flip this bit back to allow for calling into power hal again.
187 mSendUpdateImminent.store(true);
188 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800189 }
190
Alec Mouric059dcf2022-05-05 23:40:07 +0000191 if (mScreenUpdateTimer) {
192 mLastScreenUpdatedTime.store(systemTime());
Dan Stoza030fbc12020-02-19 15:32:01 -0800193 }
194}
195
Matt Buckley06f299a2021-09-24 19:43:51 +0000196bool PowerAdvisor::usePowerHintSession() {
197 // uses cached value since the underlying support and flag are unlikely to change at runtime
Matt Buckley0538cae2022-11-08 23:12:04 +0000198 return mHintSessionEnabled.value_or(false) && supportsPowerHintSession();
Matt Buckley06f299a2021-09-24 19:43:51 +0000199}
200
201bool PowerAdvisor::supportsPowerHintSession() {
Matt Buckley0538cae2022-11-08 23:12:04 +0000202 if (!mSupportsHintSession.has_value()) {
203 mSupportsHintSession = getPowerHal().getHintSessionPreferredRate().isOk();
Matt Buckley06f299a2021-09-24 19:43:51 +0000204 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000205 return *mSupportsHintSession;
Matt Buckley06f299a2021-09-24 19:43:51 +0000206}
207
Matt Buckley52dfaad2024-03-07 20:20:07 +0000208bool PowerAdvisor::shouldCreateSessionWithConfig() {
Xiang Wangcb50bbd2024-04-18 16:57:54 -0700209 return mSessionConfigSupported && mBootFinished &&
210 FlagManager::getInstance().adpf_use_fmq_channel();
Matt Buckley52dfaad2024-03-07 20:20:07 +0000211}
212
Matt Buckley0538cae2022-11-08 23:12:04 +0000213bool PowerAdvisor::ensurePowerHintSessionRunning() {
Matt Buckley547cc0c2023-10-27 22:22:36 +0000214 if (mHintSession == nullptr && !mHintSessionThreadIds.empty() && usePowerHintSession()) {
Matt Buckley52dfaad2024-03-07 20:20:07 +0000215 if (shouldCreateSessionWithConfig()) {
216 auto ret = getPowerHal().createHintSessionWithConfig(getpid(),
217 static_cast<int32_t>(getuid()),
218 mHintSessionThreadIds,
219 mTargetDuration.ns(),
220 SessionTag::SURFACEFLINGER,
221 &mSessionConfig);
222 if (ret.isOk()) {
223 mHintSession = ret.value();
224 }
225 // If it fails the first time we try, or ever returns unsupported, assume unsupported
226 else if (mFirstConfigSupportCheck || ret.isUnsupported()) {
227 ALOGI("Hint session with config is unsupported, falling back to a legacy session");
228 mSessionConfigSupported = false;
229 }
230 mFirstConfigSupportCheck = false;
231 }
232 // Immediately try original method after, in case the first way returned unsupported
233 if (mHintSession == nullptr && !shouldCreateSessionWithConfig()) {
234 auto ret = getPowerHal().createHintSession(getpid(), static_cast<int32_t>(getuid()),
235 mHintSessionThreadIds, mTargetDuration.ns());
236 if (ret.isOk()) {
237 mHintSession = ret.value();
238 }
Matt Buckley547cc0c2023-10-27 22:22:36 +0000239 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000240 }
Matt Buckley547cc0c2023-10-27 22:22:36 +0000241 return mHintSession != nullptr;
Matt Buckley06f299a2021-09-24 19:43:51 +0000242}
243
Matt Buckley0538cae2022-11-08 23:12:04 +0000244void PowerAdvisor::updateTargetWorkDuration(Duration targetDuration) {
Xiang Wangcb50bbd2024-04-18 16:57:54 -0700245 if (!mBootFinished || !usePowerHintSession()) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000246 ALOGV("Power hint session target duration cannot be set, skipping");
247 return;
248 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000249 ATRACE_CALL();
Matt Buckley06f299a2021-09-24 19:43:51 +0000250 {
Matt Buckley0538cae2022-11-08 23:12:04 +0000251 mTargetDuration = targetDuration;
252 if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration.ns());
Matt Buckley547cc0c2023-10-27 22:22:36 +0000253 if (targetDuration == mLastTargetDurationSent) return;
254 std::lock_guard lock(mHintSessionMutex);
255 if (ensurePowerHintSessionRunning()) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000256 ALOGV("Sending target time: %" PRId64 "ns", targetDuration.ns());
257 mLastTargetDurationSent = targetDuration;
Matt Buckley0538cae2022-11-08 23:12:04 +0000258 auto ret = mHintSession->updateTargetWorkDuration(targetDuration.ns());
259 if (!ret.isOk()) {
260 ALOGW("Failed to set power hint target work duration with error: %s",
Matt Buckley6c18e6d2024-02-07 23:39:50 +0000261 ret.errorMessage());
Matt Buckley547cc0c2023-10-27 22:22:36 +0000262 mHintSession = nullptr;
Matt Buckley0538cae2022-11-08 23:12:04 +0000263 }
Matt Buckley06f299a2021-09-24 19:43:51 +0000264 }
265 }
266}
267
Matt Buckley0538cae2022-11-08 23:12:04 +0000268void PowerAdvisor::reportActualWorkDuration() {
Matt Buckley676e4392023-05-25 22:09:26 +0000269 if (!mBootFinished || !sUseReportActualDuration || !usePowerHintSession()) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000270 ALOGV("Actual work duration power hint cannot be sent, skipping");
271 return;
272 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000273 ATRACE_CALL();
Xiang Wangaab31162024-03-12 19:48:08 -0700274 std::optional<WorkDuration> actualDuration = estimateWorkDuration();
275 if (!actualDuration.has_value() || actualDuration->durationNanos < 0) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000276 ALOGV("Failed to send actual work duration, skipping");
Matt Buckley50c44062022-01-17 20:48:10 +0000277 return;
278 }
Xiang Wangaab31162024-03-12 19:48:08 -0700279 actualDuration->durationNanos += sTargetSafetyMargin.ns();
Matt Buckley0538cae2022-11-08 23:12:04 +0000280 if (sTraceHintSessionData) {
Xiang Wangaab31162024-03-12 19:48:08 -0700281 ATRACE_INT64("Measured duration", actualDuration->durationNanos);
282 ATRACE_INT64("Target error term", actualDuration->durationNanos - mTargetDuration.ns());
283 ATRACE_INT64("Reported duration", actualDuration->durationNanos);
Xiang Wangcb50bbd2024-04-18 16:57:54 -0700284 if (supportsGpuReporting()) {
Xiang Wangaab31162024-03-12 19:48:08 -0700285 ATRACE_INT64("Reported cpu duration", actualDuration->cpuDurationNanos);
286 ATRACE_INT64("Reported gpu duration", actualDuration->gpuDurationNanos);
287 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000288 ATRACE_INT64("Reported target", mLastTargetDurationSent.ns());
289 ATRACE_INT64("Reported target error term",
Xiang Wangaab31162024-03-12 19:48:08 -0700290 actualDuration->durationNanos - mLastTargetDurationSent.ns());
Matt Buckley0538cae2022-11-08 23:12:04 +0000291 }
292
Xiang Wangaab31162024-03-12 19:48:08 -0700293 ALOGV("Sending actual work duration of: %" PRId64 " with cpu: %" PRId64 " and gpu: %" PRId64
294 " on reported target: %" PRId64 " with error: %" PRId64,
295 actualDuration->durationNanos, actualDuration->cpuDurationNanos,
296 actualDuration->gpuDurationNanos, mLastTargetDurationSent.ns(),
297 actualDuration->durationNanos - mLastTargetDurationSent.ns());
Matt Buckley0538cae2022-11-08 23:12:04 +0000298
Matt Buckley547cc0c2023-10-27 22:22:36 +0000299 if (mTimingTestingMode) {
300 mDelayReportActualMutexAcquisitonPromise.get_future().wait();
301 mDelayReportActualMutexAcquisitonPromise = std::promise<bool>{};
302 }
303
Matt Buckley0538cae2022-11-08 23:12:04 +0000304 {
305 std::lock_guard lock(mHintSessionMutex);
Matt Buckley547cc0c2023-10-27 22:22:36 +0000306 if (!ensurePowerHintSessionRunning()) {
307 ALOGV("Hint session not running and could not be started, skipping");
308 return;
309 }
Xiang Wangaab31162024-03-12 19:48:08 -0700310 mHintSessionQueue.push_back(*actualDuration);
Matt Buckley547cc0c2023-10-27 22:22:36 +0000311
Matt Buckley0538cae2022-11-08 23:12:04 +0000312 auto ret = mHintSession->reportActualWorkDuration(mHintSessionQueue);
313 if (!ret.isOk()) {
Matt Buckley6c18e6d2024-02-07 23:39:50 +0000314 ALOGW("Failed to report actual work durations with error: %s", ret.errorMessage());
Matt Buckley547cc0c2023-10-27 22:22:36 +0000315 mHintSession = nullptr;
Matt Buckley0538cae2022-11-08 23:12:04 +0000316 return;
Matt Buckley50c44062022-01-17 20:48:10 +0000317 }
318 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000319 mHintSessionQueue.clear();
Matt Buckley50c44062022-01-17 20:48:10 +0000320}
321
Matt Buckley0538cae2022-11-08 23:12:04 +0000322void PowerAdvisor::enablePowerHintSession(bool enabled) {
323 mHintSessionEnabled = enabled;
Matt Buckley06f299a2021-09-24 19:43:51 +0000324}
325
Matt Buckley547cc0c2023-10-27 22:22:36 +0000326bool PowerAdvisor::startPowerHintSession(std::vector<int32_t>&& threadIds) {
327 mHintSessionThreadIds = threadIds;
Matt Buckley0538cae2022-11-08 23:12:04 +0000328 if (!mBootFinished.load()) {
329 return false;
Matt Buckleyef51fba2021-10-12 19:30:12 +0000330 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000331 if (!usePowerHintSession()) {
332 ALOGI("Cannot start power hint session: disabled or unsupported");
333 return false;
334 }
Matt Buckley547cc0c2023-10-27 22:22:36 +0000335 LOG_ALWAYS_FATAL_IF(mHintSessionThreadIds.empty(),
336 "No thread IDs provided to power hint session!");
337 std::lock_guard lock(mHintSessionMutex);
338 if (mHintSession != nullptr) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000339 ALOGE("Cannot start power hint session: already running");
340 return false;
341 }
Matt Buckley547cc0c2023-10-27 22:22:36 +0000342 return ensurePowerHintSessionRunning();
Matt Buckleyef51fba2021-10-12 19:30:12 +0000343}
344
Xiang Wangcb50bbd2024-04-18 16:57:54 -0700345bool PowerAdvisor::supportsGpuReporting() {
346 return mBootFinished && FlagManager::getInstance().adpf_gpu_sf();
347}
348
Xiang Wangaab31162024-03-12 19:48:08 -0700349void PowerAdvisor::setGpuStartTime(DisplayId displayId, TimePoint startTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000350 DisplayTimingData& displayData = mDisplayTimingData[displayId];
351 if (displayData.gpuEndFenceTime) {
352 nsecs_t signalTime = displayData.gpuEndFenceTime->getSignalTime();
353 if (signalTime != Fence::SIGNAL_TIME_INVALID && signalTime != Fence::SIGNAL_TIME_PENDING) {
Xiang Wangaab31162024-03-12 19:48:08 -0700354 displayData.lastValidGpuStartTime = displayData.gpuStartTime;
355 displayData.lastValidGpuEndTime = TimePoint::fromNs(signalTime);
356 for (auto&& [_, otherDisplayData] : mDisplayTimingData) {
357 if (!otherDisplayData.lastValidGpuStartTime.has_value() ||
358 !otherDisplayData.lastValidGpuEndTime.has_value())
359 continue;
360 if ((*otherDisplayData.lastValidGpuStartTime < *displayData.gpuStartTime) &&
361 (*otherDisplayData.lastValidGpuEndTime > *displayData.gpuStartTime)) {
362 displayData.lastValidGpuStartTime = *otherDisplayData.lastValidGpuEndTime;
363 break;
364 }
365 }
366 }
367 displayData.gpuEndFenceTime = nullptr;
368 }
369 displayData.gpuStartTime = startTime;
370}
371
372void PowerAdvisor::setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime) {
373 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Xiang Wangcb50bbd2024-04-18 16:57:54 -0700374 if (displayData.gpuEndFenceTime && !supportsGpuReporting()) {
Xiang Wangaab31162024-03-12 19:48:08 -0700375 nsecs_t signalTime = displayData.gpuEndFenceTime->getSignalTime();
376 if (signalTime != Fence::SIGNAL_TIME_INVALID && signalTime != Fence::SIGNAL_TIME_PENDING) {
377 displayData.lastValidGpuStartTime = displayData.gpuStartTime;
378 displayData.lastValidGpuEndTime = TimePoint::fromNs(signalTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000379 for (auto&& [_, otherDisplayData] : mDisplayTimingData) {
380 // If the previous display started before us but ended after we should have
381 // started, then it likely delayed our start time and we must compensate for that.
382 // Displays finishing earlier should have already made their way through this call
383 // and swapped their timing into "lastValid" from "latest", so we check that here.
384 if (!otherDisplayData.lastValidGpuStartTime.has_value()) continue;
385 if ((*otherDisplayData.lastValidGpuStartTime < *displayData.gpuStartTime) &&
386 (*otherDisplayData.lastValidGpuEndTime > *displayData.gpuStartTime)) {
387 displayData.lastValidGpuStartTime = *otherDisplayData.lastValidGpuEndTime;
388 break;
389 }
390 }
Matt Buckley50c44062022-01-17 20:48:10 +0000391 }
392 }
393 displayData.gpuEndFenceTime = std::move(fenceTime);
Xiang Wangcb50bbd2024-04-18 16:57:54 -0700394 if (!supportsGpuReporting()) {
Xiang Wangaab31162024-03-12 19:48:08 -0700395 displayData.gpuStartTime = TimePoint::now();
396 }
Matt Buckley50c44062022-01-17 20:48:10 +0000397}
398
Matt Buckley2fa85012022-08-30 22:38:45 +0000399void PowerAdvisor::setHwcValidateTiming(DisplayId displayId, TimePoint validateStartTime,
400 TimePoint validateEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000401 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000402 displayData.hwcValidateStartTime = validateStartTime;
403 displayData.hwcValidateEndTime = validateEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000404}
405
Matt Buckley2fa85012022-08-30 22:38:45 +0000406void PowerAdvisor::setHwcPresentTiming(DisplayId displayId, TimePoint presentStartTime,
407 TimePoint presentEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000408 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000409 displayData.hwcPresentStartTime = presentStartTime;
410 displayData.hwcPresentEndTime = presentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000411}
412
413void PowerAdvisor::setSkippedValidate(DisplayId displayId, bool skipped) {
414 mDisplayTimingData[displayId].skippedValidate = skipped;
415}
416
Xiang Wangaab31162024-03-12 19:48:08 -0700417void PowerAdvisor::setRequiresRenderEngine(DisplayId displayId, bool requiresRenderEngine) {
418 mDisplayTimingData[displayId].requiresRenderEngine = requiresRenderEngine;
Matt Buckley50c44062022-01-17 20:48:10 +0000419}
420
Matt Buckley2fa85012022-08-30 22:38:45 +0000421void PowerAdvisor::setExpectedPresentTime(TimePoint expectedPresentTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000422 mExpectedPresentTimes.append(expectedPresentTime);
423}
424
Matt Buckley2fa85012022-08-30 22:38:45 +0000425void PowerAdvisor::setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) {
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700426 mLastPresentFenceTime = presentFenceTime;
Xiang Wangaab31162024-03-12 19:48:08 -0700427 mLastSfPresentEndTime = presentEndTime;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700428}
429
Matt Buckley2fa85012022-08-30 22:38:45 +0000430void PowerAdvisor::setFrameDelay(Duration frameDelayDuration) {
Matt Buckley50c44062022-01-17 20:48:10 +0000431 mFrameDelayDuration = frameDelayDuration;
432}
433
Matt Buckley2fa85012022-08-30 22:38:45 +0000434void PowerAdvisor::setHwcPresentDelayedTime(DisplayId displayId, TimePoint earliestFrameStartTime) {
435 mDisplayTimingData[displayId].hwcPresentDelayedTime = earliestFrameStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000436}
437
Matt Buckley2fa85012022-08-30 22:38:45 +0000438void PowerAdvisor::setCommitStart(TimePoint commitStartTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000439 mCommitStartTimes.append(commitStartTime);
440}
441
Matt Buckley2fa85012022-08-30 22:38:45 +0000442void PowerAdvisor::setCompositeEnd(TimePoint compositeEndTime) {
443 mLastPostcompDuration = compositeEndTime - mLastSfPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000444}
445
446void PowerAdvisor::setDisplays(std::vector<DisplayId>& displayIds) {
447 mDisplayIds = displayIds;
448}
449
Matt Buckley2fa85012022-08-30 22:38:45 +0000450void PowerAdvisor::setTotalFrameTargetWorkDuration(Duration targetDuration) {
Matt Buckley50c44062022-01-17 20:48:10 +0000451 mTotalFrameTargetDuration = targetDuration;
452}
453
454std::vector<DisplayId> PowerAdvisor::getOrderedDisplayIds(
Matt Buckley2fa85012022-08-30 22:38:45 +0000455 std::optional<TimePoint> DisplayTimingData::*sortBy) {
Matt Buckley50c44062022-01-17 20:48:10 +0000456 std::vector<DisplayId> sortedDisplays;
457 std::copy_if(mDisplayIds.begin(), mDisplayIds.end(), std::back_inserter(sortedDisplays),
458 [&](DisplayId id) {
459 return mDisplayTimingData.count(id) &&
460 (mDisplayTimingData[id].*sortBy).has_value();
461 });
462 std::sort(sortedDisplays.begin(), sortedDisplays.end(), [&](DisplayId idA, DisplayId idB) {
463 return *(mDisplayTimingData[idA].*sortBy) < *(mDisplayTimingData[idB].*sortBy);
464 });
465 return sortedDisplays;
466}
467
Xiang Wangaab31162024-03-12 19:48:08 -0700468std::optional<WorkDuration> PowerAdvisor::estimateWorkDuration() {
Matt Buckley0538cae2022-11-08 23:12:04 +0000469 if (!mExpectedPresentTimes.isFull() || !mCommitStartTimes.isFull()) {
Matt Buckley50c44062022-01-17 20:48:10 +0000470 return std::nullopt;
471 }
472
473 // Tracks when we finish presenting to hwc
Matt Buckley0538cae2022-11-08 23:12:04 +0000474 TimePoint estimatedHwcEndTime = mCommitStartTimes[0];
Matt Buckley50c44062022-01-17 20:48:10 +0000475
476 // How long we spent this frame not doing anything, waiting for fences or vsync
Matt Buckley2fa85012022-08-30 22:38:45 +0000477 Duration idleDuration = 0ns;
Matt Buckley50c44062022-01-17 20:48:10 +0000478
479 // Most recent previous gpu end time in the current frame, probably from a prior display, used
480 // 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 +0000481 std::optional<TimePoint> previousValidGpuEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000482
483 // The currently estimated gpu end time for the frame,
484 // used to accumulate gpu time as we iterate over the active displays
Matt Buckley2fa85012022-08-30 22:38:45 +0000485 std::optional<TimePoint> estimatedGpuEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000486
Matt Buckley50c44062022-01-17 20:48:10 +0000487 std::vector<DisplayId>&& displayIds =
Matt Buckley16dec1f2022-06-07 21:46:20 +0000488 getOrderedDisplayIds(&DisplayTimingData::hwcPresentStartTime);
Matt Buckley0538cae2022-11-08 23:12:04 +0000489 DisplayTimeline displayTiming;
Xiang Wangaab31162024-03-12 19:48:08 -0700490 std::optional<GpuTimeline> firstGpuTimeline;
Matt Buckley50c44062022-01-17 20:48:10 +0000491
Matt Buckley1809d902022-08-05 06:51:43 +0000492 // Iterate over the displays that use hwc in the same order they are presented
Matt Buckley50c44062022-01-17 20:48:10 +0000493 for (DisplayId displayId : displayIds) {
494 if (mDisplayTimingData.count(displayId) == 0) {
495 continue;
496 }
497
498 auto& displayData = mDisplayTimingData.at(displayId);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700499
Matt Buckley0538cae2022-11-08 23:12:04 +0000500 displayTiming = displayData.calculateDisplayTimeline(mLastPresentFenceTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000501
Matt Buckley50c44062022-01-17 20:48:10 +0000502 // Update predicted present finish time with this display's present time
Matt Buckley0538cae2022-11-08 23:12:04 +0000503 estimatedHwcEndTime = displayTiming.hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000504
505 // Track how long we spent waiting for the fence, can be excluded from the timing estimate
Matt Buckley0538cae2022-11-08 23:12:04 +0000506 idleDuration += displayTiming.probablyWaitsForPresentFence
507 ? mLastPresentFenceTime - displayTiming.presentFenceWaitStartTime
Matt Buckley2fa85012022-08-30 22:38:45 +0000508 : 0ns;
Matt Buckley50c44062022-01-17 20:48:10 +0000509
510 // Track how long we spent waiting to present, can be excluded from the timing estimate
Matt Buckley0538cae2022-11-08 23:12:04 +0000511 idleDuration += displayTiming.hwcPresentDelayDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000512
513 // Estimate the reference frame's gpu timing
514 auto gpuTiming = displayData.estimateGpuTiming(previousValidGpuEndTime);
515 if (gpuTiming.has_value()) {
Xiang Wangaab31162024-03-12 19:48:08 -0700516 if (!firstGpuTimeline.has_value()) {
517 firstGpuTimeline = gpuTiming;
518 }
Matt Buckley50c44062022-01-17 20:48:10 +0000519 previousValidGpuEndTime = gpuTiming->startTime + gpuTiming->duration;
520
521 // Estimate the prediction frame's gpu end time from the reference frame
Matt Buckley0538cae2022-11-08 23:12:04 +0000522 estimatedGpuEndTime = std::max(displayTiming.hwcPresentStartTime,
Matt Buckley2fa85012022-08-30 22:38:45 +0000523 estimatedGpuEndTime.value_or(TimePoint{0ns})) +
Matt Buckley50c44062022-01-17 20:48:10 +0000524 gpuTiming->duration;
525 }
Matt Buckley50c44062022-01-17 20:48:10 +0000526 }
Matt Buckley50c44062022-01-17 20:48:10 +0000527
Matt Buckley0538cae2022-11-08 23:12:04 +0000528 TimePoint estimatedFlingerEndTime = mLastSfPresentEndTime;
Matt Buckley1809d902022-08-05 06:51:43 +0000529
Matt Buckley50c44062022-01-17 20:48:10 +0000530 // 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 +0000531 estimatedHwcEndTime -= idleDuration;
Matt Buckley1809d902022-08-05 06:51:43 +0000532 estimatedFlingerEndTime -= idleDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000533
534 // We finish the frame when both present and the gpu are done, so wait for the later of the two
535 // Also add the frame delay duration since the target did not move while we were delayed
Matt Buckley2fa85012022-08-30 22:38:45 +0000536 Duration totalDuration = mFrameDelayDuration +
Matt Buckley0538cae2022-11-08 23:12:04 +0000537 std::max(estimatedHwcEndTime, estimatedGpuEndTime.value_or(TimePoint{0ns})) -
Matt Buckley2fa85012022-08-30 22:38:45 +0000538 mCommitStartTimes[0];
Xiang Wangaab31162024-03-12 19:48:08 -0700539 Duration totalDurationWithoutGpu =
540 mFrameDelayDuration + estimatedHwcEndTime - mCommitStartTimes[0];
Matt Buckley50c44062022-01-17 20:48:10 +0000541
542 // We finish SurfaceFlinger when post-composition finishes, so add that in here
Matt Buckley2fa85012022-08-30 22:38:45 +0000543 Duration flingerDuration =
Matt Buckley1809d902022-08-05 06:51:43 +0000544 estimatedFlingerEndTime + mLastPostcompDuration - mCommitStartTimes[0];
Xiang Wangaab31162024-03-12 19:48:08 -0700545 Duration estimatedGpuDuration = firstGpuTimeline.has_value()
546 ? estimatedGpuEndTime.value_or(TimePoint{0ns}) - firstGpuTimeline->startTime
547 : Duration::fromNs(0);
Matt Buckley1809d902022-08-05 06:51:43 +0000548
549 // Combine the two timings into a single normalized one
Matt Buckley2fa85012022-08-30 22:38:45 +0000550 Duration combinedDuration = combineTimingEstimates(totalDuration, flingerDuration);
Xiang Wangaab31162024-03-12 19:48:08 -0700551 Duration cpuDuration = combineTimingEstimates(totalDurationWithoutGpu, flingerDuration);
Matt Buckley50c44062022-01-17 20:48:10 +0000552
Xiang Wangaab31162024-03-12 19:48:08 -0700553 WorkDuration duration{
554 .timeStampNanos = TimePoint::now().ns(),
555 .durationNanos = combinedDuration.ns(),
556 .workPeriodStartTimestampNanos = mCommitStartTimes[0].ns(),
Xiang Wangcb50bbd2024-04-18 16:57:54 -0700557 .cpuDurationNanos = supportsGpuReporting() ? cpuDuration.ns() : 0,
558 .gpuDurationNanos = supportsGpuReporting() ? estimatedGpuDuration.ns() : 0,
Xiang Wangaab31162024-03-12 19:48:08 -0700559 };
560 if (sTraceHintSessionData) {
561 ATRACE_INT64("Idle duration", idleDuration.ns());
Xiang Wangaab31162024-03-12 19:48:08 -0700562 ATRACE_INT64("Total duration", totalDuration.ns());
563 ATRACE_INT64("Flinger duration", flingerDuration.ns());
564 }
565 return std::make_optional(duration);
Matt Buckley50c44062022-01-17 20:48:10 +0000566}
567
Matt Buckley2fa85012022-08-30 22:38:45 +0000568Duration PowerAdvisor::combineTimingEstimates(Duration totalDuration, Duration flingerDuration) {
569 Duration targetDuration{0ns};
Matt Buckley0538cae2022-11-08 23:12:04 +0000570 targetDuration = mTargetDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000571 if (!mTotalFrameTargetDuration.has_value()) return flingerDuration;
572
573 // Normalize total to the flinger target (vsync period) since that's how often we actually send
574 // hints
Matt Buckley2fa85012022-08-30 22:38:45 +0000575 Duration normalizedTotalDuration = Duration::fromNs((targetDuration.ns() * totalDuration.ns()) /
576 mTotalFrameTargetDuration->ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000577 return std::max(flingerDuration, normalizedTotalDuration);
578}
579
Matt Buckley50c44062022-01-17 20:48:10 +0000580PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimingData::calculateDisplayTimeline(
Matt Buckley2fa85012022-08-30 22:38:45 +0000581 TimePoint fenceTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000582 DisplayTimeline timeline;
Matt Buckley16dec1f2022-06-07 21:46:20 +0000583 // How long between calling hwc present and trying to wait on the fence
Matt Buckley2fa85012022-08-30 22:38:45 +0000584 const Duration fenceWaitStartDelay =
585 (skippedValidate ? kFenceWaitStartDelaySkippedValidate : kFenceWaitStartDelayValidated);
Matt Buckley50c44062022-01-17 20:48:10 +0000586
Matt Buckley16dec1f2022-06-07 21:46:20 +0000587 // Did our reference frame wait for an appropriate vsync before calling into hwc
588 const bool waitedOnHwcPresentTime = hwcPresentDelayedTime.has_value() &&
589 *hwcPresentDelayedTime > *hwcPresentStartTime &&
590 *hwcPresentDelayedTime < *hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000591
592 // Use validate start here if we skipped it because we did validate + present together
Matt Buckley16dec1f2022-06-07 21:46:20 +0000593 timeline.hwcPresentStartTime = skippedValidate ? *hwcValidateStartTime : *hwcPresentStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000594
595 // Use validate end here if we skipped it because we did validate + present together
Matt Buckley16dec1f2022-06-07 21:46:20 +0000596 timeline.hwcPresentEndTime = skippedValidate ? *hwcValidateEndTime : *hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000597
Matt Buckley16dec1f2022-06-07 21:46:20 +0000598 // How long hwc present was delayed waiting for the next appropriate vsync
599 timeline.hwcPresentDelayDuration =
Matt Buckley2fa85012022-08-30 22:38:45 +0000600 (waitedOnHwcPresentTime ? *hwcPresentDelayedTime - *hwcPresentStartTime : 0ns);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700601 // When we started waiting for the present fence after calling into hwc present
602 timeline.presentFenceWaitStartTime =
Matt Buckley16dec1f2022-06-07 21:46:20 +0000603 timeline.hwcPresentStartTime + timeline.hwcPresentDelayDuration + fenceWaitStartDelay;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700604 timeline.probablyWaitsForPresentFence = fenceTime > timeline.presentFenceWaitStartTime &&
Matt Buckley16dec1f2022-06-07 21:46:20 +0000605 fenceTime < timeline.hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000606
Matt Buckley16dec1f2022-06-07 21:46:20 +0000607 // How long we ran after we finished waiting for the fence but before hwc present finished
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700608 timeline.postPresentFenceHwcPresentDuration = timeline.hwcPresentEndTime -
609 (timeline.probablyWaitsForPresentFence ? fenceTime
610 : timeline.presentFenceWaitStartTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000611 return timeline;
612}
613
614std::optional<PowerAdvisor::GpuTimeline> PowerAdvisor::DisplayTimingData::estimateGpuTiming(
Matt Buckley2fa85012022-08-30 22:38:45 +0000615 std::optional<TimePoint> previousEndTime) {
Xiang Wangaab31162024-03-12 19:48:08 -0700616 if (!(requiresRenderEngine && lastValidGpuStartTime.has_value() && gpuEndFenceTime)) {
Matt Buckley50c44062022-01-17 20:48:10 +0000617 return std::nullopt;
618 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000619 const TimePoint latestGpuStartTime =
620 std::max(previousEndTime.value_or(TimePoint{0ns}), *gpuStartTime);
621 const nsecs_t gpuEndFenceSignal = gpuEndFenceTime->getSignalTime();
622 Duration gpuDuration{0ns};
623 if (gpuEndFenceSignal != Fence::SIGNAL_TIME_INVALID &&
624 gpuEndFenceSignal != Fence::SIGNAL_TIME_PENDING) {
625 const TimePoint latestGpuEndTime = TimePoint::fromNs(gpuEndFenceSignal);
626
Matt Buckley50c44062022-01-17 20:48:10 +0000627 // If we know how long the most recent gpu duration was, use that
628 gpuDuration = latestGpuEndTime - latestGpuStartTime;
629 } else if (lastValidGpuEndTime.has_value()) {
630 // If we don't have the fence data, use the most recent information we do have
631 gpuDuration = *lastValidGpuEndTime - *lastValidGpuStartTime;
Matt Buckley2fa85012022-08-30 22:38:45 +0000632 if (gpuEndFenceSignal == Fence::SIGNAL_TIME_PENDING) {
Matt Buckley50c44062022-01-17 20:48:10 +0000633 // If pending but went over the previous duration, use current time as the end
Matt Buckley2fa85012022-08-30 22:38:45 +0000634 gpuDuration = std::max(gpuDuration, Duration{TimePoint::now() - latestGpuStartTime});
Matt Buckley50c44062022-01-17 20:48:10 +0000635 }
636 }
637 return GpuTimeline{.duration = gpuDuration, .startTime = latestGpuStartTime};
638}
639
Matt Buckley0538cae2022-11-08 23:12:04 +0000640const bool PowerAdvisor::sTraceHintSessionData =
Xiang Wang56dc1042024-03-22 03:58:46 +0000641 base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
Matt Buckleyef51fba2021-10-12 19:30:12 +0000642
Matt Buckleyac15a1b2023-02-28 06:51:28 +0000643const Duration PowerAdvisor::sTargetSafetyMargin = std::chrono::microseconds(
644 base::GetIntProperty<int64_t>("debug.sf.hint_margin_us",
645 ticks<std::micro>(PowerAdvisor::kDefaultTargetSafetyMargin)));
646
Matt Buckley676e4392023-05-25 22:09:26 +0000647const bool PowerAdvisor::sUseReportActualDuration =
648 base::GetBoolProperty(std::string("debug.adpf.use_report_actual_duration"), true);
649
Matt Buckley0538cae2022-11-08 23:12:04 +0000650power::PowerHalController& PowerAdvisor::getPowerHal() {
651 static std::once_flag halFlag;
652 std::call_once(halFlag, [this] { mPowerHal->init(); });
653 return *mPowerHal;
Michael Wright1509a232018-06-21 02:50:34 +0100654}
655
656} // namespace impl
657} // namespace Hwc2
658} // namespace android