blob: 730db40f7afbc39dbb302b70bfea1773331dab89 [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
Xiang Wang99f6f3c2023-05-22 13:12:16 -070034#include <aidl/android/hardware/power/IPower.h>
35#include <aidl/android/hardware/power/IPowerHintSession.h>
36#include <aidl/android/hardware/power/WorkDuration.h>
Matt Buckley06f299a2021-09-24 19:43:51 +000037
Dan Stoza030fbc12020-02-19 15:32:01 -080038#include <binder/IServiceManager.h>
39
40#include "../SurfaceFlingerProperties.h"
41
Michael Wright1509a232018-06-21 02:50:34 +010042#include "PowerAdvisor.h"
Alec Mouridea1ac52021-06-23 18:12:18 -070043#include "SurfaceFlinger.h"
Michael Wright1509a232018-06-21 02:50:34 +010044
45namespace android {
46namespace Hwc2 {
47
48PowerAdvisor::~PowerAdvisor() = default;
49
50namespace impl {
51
Xiang Wang99f6f3c2023-05-22 13:12:16 -070052using aidl::android::hardware::power::Boost;
53using aidl::android::hardware::power::IPowerHintSession;
54using aidl::android::hardware::power::Mode;
55using aidl::android::hardware::power::SessionHint;
56using aidl::android::hardware::power::WorkDuration;
Matt Buckley06f299a2021-09-24 19:43:51 +000057
Michael Wright1509a232018-06-21 02:50:34 +010058PowerAdvisor::~PowerAdvisor() = default;
59
Dan Stoza030fbc12020-02-19 15:32:01 -080060namespace {
Alec Mouri29382ad2022-05-11 18:38:38 +000061std::chrono::milliseconds getUpdateTimeout() {
Dan Stoza030fbc12020-02-19 15:32:01 -080062 // Default to a timeout of 80ms if nothing else is specified
Alec Mouri29382ad2022-05-11 18:38:38 +000063 static std::chrono::milliseconds timeout =
64 std::chrono::milliseconds(sysprop::display_update_imminent_timeout_ms(80));
Dan Stoza030fbc12020-02-19 15:32:01 -080065 return timeout;
66}
67
Ady Abrahamabce1652022-02-24 10:51:19 -080068void traceExpensiveRendering(bool enabled) {
69 if (enabled) {
70 ATRACE_ASYNC_BEGIN("ExpensiveRendering", 0);
71 } else {
72 ATRACE_ASYNC_END("ExpensiveRendering", 0);
73 }
74}
75
Dan Stoza030fbc12020-02-19 15:32:01 -080076} // namespace
77
Matt Buckleycbfe23c2022-11-08 23:12:04 +000078PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger)
79 : mPowerHal(std::make_unique<power::PowerHalController>()), mFlinger(flinger) {
Alec Mouri29382ad2022-05-11 18:38:38 +000080 if (getUpdateTimeout() > 0ms) {
81 mScreenUpdateTimer.emplace("UpdateImminentTimer", getUpdateTimeout(),
Alec Mouric059dcf2022-05-05 23:40:07 +000082 /* resetCallback */ nullptr,
83 /* timeoutCallback */
84 [this] {
Alec Mouri29382ad2022-05-11 18:38:38 +000085 while (true) {
86 auto timeSinceLastUpdate = std::chrono::nanoseconds(
87 systemTime() - mLastScreenUpdatedTime.load());
88 if (timeSinceLastUpdate >= getUpdateTimeout()) {
89 break;
90 }
Alec Mouric059dcf2022-05-05 23:40:07 +000091 // We may try to disable expensive rendering and allow
92 // for sending DISPLAY_UPDATE_IMMINENT hints too early if
93 // we idled very shortly after updating the screen, so
94 // make sure we wait enough time.
Alec Mouri29382ad2022-05-11 18:38:38 +000095 std::this_thread::sleep_for(getUpdateTimeout() -
96 timeSinceLastUpdate);
Alec Mouric059dcf2022-05-05 23:40:07 +000097 }
98 mSendUpdateImminent.store(true);
99 mFlinger.disableExpensiveRendering();
100 });
101 }
102}
Alec Mouridea1ac52021-06-23 18:12:18 -0700103
104void PowerAdvisor::init() {
105 // Defer starting the screen update timer until SurfaceFlinger finishes construction.
Alec Mouric059dcf2022-05-05 23:40:07 +0000106 if (mScreenUpdateTimer) {
107 mScreenUpdateTimer->start();
Dan Stoza030fbc12020-02-19 15:32:01 -0800108 }
109}
Michael Wright1509a232018-06-21 02:50:34 +0100110
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700111void PowerAdvisor::onBootFinished() {
112 mBootFinished.store(true);
113}
114
Peiyong Lin74ca2f42019-01-14 19:36:57 -0800115void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000116 if (!mHasExpensiveRendering) {
117 ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
118 return;
119 }
Michael Wright1509a232018-06-21 02:50:34 +0100120 if (expected) {
121 mExpensiveDisplays.insert(displayId);
122 } else {
123 mExpensiveDisplays.erase(displayId);
124 }
125
Michael Wright1509a232018-06-21 02:50:34 +0100126 const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
127 if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000128 auto ret = getPowerHal().setMode(Mode::EXPENSIVE_RENDERING, expectsExpensiveRendering);
129 if (!ret.isOk()) {
130 if (ret.isUnsupported()) {
131 mHasExpensiveRendering = false;
132 }
Michael Wright1509a232018-06-21 02:50:34 +0100133 return;
134 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800135
Michael Wright1509a232018-06-21 02:50:34 +0100136 mNotifiedExpensiveRendering = expectsExpensiveRendering;
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000137 traceExpensiveRendering(mNotifiedExpensiveRendering);
Michael Wright1509a232018-06-21 02:50:34 +0100138 }
139}
140
Matt Buckley15ecd1c2022-11-01 21:57:16 +0000141void PowerAdvisor::notifyDisplayUpdateImminentAndCpuReset() {
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700142 // Only start sending this notification once the system has booted so we don't introduce an
143 // early-boot dependency on Power HAL
144 if (!mBootFinished.load()) {
145 return;
146 }
147
Alec Mouric059dcf2022-05-05 23:40:07 +0000148 if (mSendUpdateImminent.exchange(false)) {
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000149 ALOGV("AIDL notifyDisplayUpdateImminentAndCpuReset");
150 if (usePowerHintSession() && ensurePowerHintSessionRunning()) {
151 std::lock_guard lock(mHintSessionMutex);
152 auto ret = mHintSession->sendHint(SessionHint::CPU_LOAD_RESET);
153 if (!ret.isOk()) {
154 mHintSessionRunning = false;
155 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800156 }
157
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000158 if (!mHasDisplayUpdateImminent) {
159 ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
160 } else {
161 auto ret = getPowerHal().setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
162 if (ret.isUnsupported()) {
163 mHasDisplayUpdateImminent = false;
164 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800165 }
Alec Mouric059dcf2022-05-05 23:40:07 +0000166
167 if (mScreenUpdateTimer) {
168 mScreenUpdateTimer->reset();
169 } else {
170 // If we don't have a screen update timer, then we don't throttle power hal calls so
171 // flip this bit back to allow for calling into power hal again.
172 mSendUpdateImminent.store(true);
173 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800174 }
175
Alec Mouric059dcf2022-05-05 23:40:07 +0000176 if (mScreenUpdateTimer) {
177 mLastScreenUpdatedTime.store(systemTime());
Dan Stoza030fbc12020-02-19 15:32:01 -0800178 }
179}
180
Matt Buckley06f299a2021-09-24 19:43:51 +0000181// checks both if it supports and if it's enabled
182bool PowerAdvisor::usePowerHintSession() {
183 // uses cached value since the underlying support and flag are unlikely to change at runtime
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000184 return mHintSessionEnabled.value_or(false) && supportsPowerHintSession();
Matt Buckley06f299a2021-09-24 19:43:51 +0000185}
186
187bool PowerAdvisor::supportsPowerHintSession() {
188 // cache to avoid needing lock every time
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000189 if (!mSupportsHintSession.has_value()) {
190 mSupportsHintSession = getPowerHal().getHintSessionPreferredRate().isOk();
Matt Buckley06f299a2021-09-24 19:43:51 +0000191 }
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000192 return *mSupportsHintSession;
Matt Buckley06f299a2021-09-24 19:43:51 +0000193}
194
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000195bool PowerAdvisor::ensurePowerHintSessionRunning() {
196 if (!mHintSessionRunning && !mHintSessionThreadIds.empty() && usePowerHintSession()) {
197 startPowerHintSession(mHintSessionThreadIds);
198 }
199 return mHintSessionRunning;
Matt Buckley06f299a2021-09-24 19:43:51 +0000200}
201
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000202void PowerAdvisor::updateTargetWorkDuration(Duration targetDuration) {
Matt Buckleyef51fba2021-10-12 19:30:12 +0000203 if (!usePowerHintSession()) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000204 ALOGV("Power hint session target duration cannot be set, skipping");
205 return;
206 }
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000207 ATRACE_CALL();
Matt Buckley06f299a2021-09-24 19:43:51 +0000208 {
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000209 mTargetDuration = targetDuration;
210 if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration.ns());
211 if (ensurePowerHintSessionRunning() && (targetDuration != mLastTargetDurationSent)) {
212 ALOGV("Sending target time: %" PRId64 "ns", targetDuration.ns());
213 mLastTargetDurationSent = targetDuration;
214 std::lock_guard lock(mHintSessionMutex);
215 auto ret = mHintSession->updateTargetWorkDuration(targetDuration.ns());
216 if (!ret.isOk()) {
217 ALOGW("Failed to set power hint target work duration with error: %s",
Xiang Wang99f6f3c2023-05-22 13:12:16 -0700218 ret.getDescription().c_str());
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000219 mHintSessionRunning = false;
220 }
Matt Buckley06f299a2021-09-24 19:43:51 +0000221 }
222 }
223}
224
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000225void PowerAdvisor::reportActualWorkDuration() {
Matt Buckley06f299a2021-09-24 19:43:51 +0000226 if (!mBootFinished || !usePowerHintSession()) {
227 ALOGV("Actual work duration power hint cannot be sent, skipping");
228 return;
229 }
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000230 ATRACE_CALL();
231 std::optional<Duration> actualDuration = estimateWorkDuration();
232 if (!actualDuration.has_value() || actualDuration < 0ns || !ensurePowerHintSessionRunning()) {
233 ALOGV("Failed to send actual work duration, skipping");
Matt Buckley50c44062022-01-17 20:48:10 +0000234 return;
235 }
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000236 actualDuration = std::make_optional(*actualDuration + sTargetSafetyMargin);
237 mActualDuration = actualDuration;
238 WorkDuration duration;
239 duration.durationNanos = actualDuration->ns();
240 duration.timeStampNanos = TimePoint::now().ns();
241 mHintSessionQueue.push_back(duration);
Matt Buckley50c44062022-01-17 20:48:10 +0000242
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000243 if (sTraceHintSessionData) {
244 ATRACE_INT64("Measured duration", actualDuration->ns());
245 ATRACE_INT64("Target error term", Duration{*actualDuration - mTargetDuration}.ns());
246 ATRACE_INT64("Reported duration", actualDuration->ns());
247 ATRACE_INT64("Reported target", mLastTargetDurationSent.ns());
248 ATRACE_INT64("Reported target error term",
249 Duration{*actualDuration - mLastTargetDurationSent}.ns());
250 }
251
252 ALOGV("Sending actual work duration of: %" PRId64 " on reported target: %" PRId64
253 " with error: %" PRId64,
254 actualDuration->ns(), mLastTargetDurationSent.ns(),
255 Duration{*actualDuration - mLastTargetDurationSent}.ns());
256
257 {
258 std::lock_guard lock(mHintSessionMutex);
259 auto ret = mHintSession->reportActualWorkDuration(mHintSessionQueue);
260 if (!ret.isOk()) {
261 ALOGW("Failed to report actual work durations with error: %s",
Xiang Wang99f6f3c2023-05-22 13:12:16 -0700262 ret.getDescription().c_str());
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000263 mHintSessionRunning = false;
264 return;
Matt Buckley50c44062022-01-17 20:48:10 +0000265 }
266 }
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000267 mHintSessionQueue.clear();
Matt Buckley50c44062022-01-17 20:48:10 +0000268}
269
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000270void PowerAdvisor::enablePowerHintSession(bool enabled) {
271 mHintSessionEnabled = enabled;
Matt Buckley06f299a2021-09-24 19:43:51 +0000272}
273
Matt Buckleyef51fba2021-10-12 19:30:12 +0000274bool PowerAdvisor::startPowerHintSession(const std::vector<int32_t>& threadIds) {
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000275 if (!mBootFinished.load()) {
276 return false;
Matt Buckleyef51fba2021-10-12 19:30:12 +0000277 }
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000278 if (!usePowerHintSession()) {
279 ALOGI("Cannot start power hint session: disabled or unsupported");
280 return false;
281 }
282 if (mHintSessionRunning) {
283 ALOGE("Cannot start power hint session: already running");
284 return false;
285 }
286 LOG_ALWAYS_FATAL_IF(threadIds.empty(), "No thread IDs provided to power hint session!");
Matt Buckleyef51fba2021-10-12 19:30:12 +0000287 {
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000288 std::lock_guard lock(mHintSessionMutex);
289 mHintSession = nullptr;
290 mHintSessionThreadIds = threadIds;
291
292 auto ret = getPowerHal().createHintSession(getpid(), static_cast<int32_t>(getuid()),
293 threadIds, mTargetDuration.ns());
294
295 if (ret.isOk()) {
296 mHintSessionRunning = true;
297 mHintSession = ret.value();
Matt Buckleyef51fba2021-10-12 19:30:12 +0000298 }
299 }
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000300 return mHintSessionRunning;
Matt Buckleyef51fba2021-10-12 19:30:12 +0000301}
302
Matt Buckley50c44062022-01-17 20:48:10 +0000303void PowerAdvisor::setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime) {
304 DisplayTimingData& displayData = mDisplayTimingData[displayId];
305 if (displayData.gpuEndFenceTime) {
306 nsecs_t signalTime = displayData.gpuEndFenceTime->getSignalTime();
307 if (signalTime != Fence::SIGNAL_TIME_INVALID && signalTime != Fence::SIGNAL_TIME_PENDING) {
308 for (auto&& [_, otherDisplayData] : mDisplayTimingData) {
309 // If the previous display started before us but ended after we should have
310 // started, then it likely delayed our start time and we must compensate for that.
311 // Displays finishing earlier should have already made their way through this call
312 // and swapped their timing into "lastValid" from "latest", so we check that here.
313 if (!otherDisplayData.lastValidGpuStartTime.has_value()) continue;
314 if ((*otherDisplayData.lastValidGpuStartTime < *displayData.gpuStartTime) &&
315 (*otherDisplayData.lastValidGpuEndTime > *displayData.gpuStartTime)) {
316 displayData.lastValidGpuStartTime = *otherDisplayData.lastValidGpuEndTime;
317 break;
318 }
319 }
320 displayData.lastValidGpuStartTime = displayData.gpuStartTime;
Matt Buckley2fa85012022-08-30 22:38:45 +0000321 displayData.lastValidGpuEndTime = TimePoint::fromNs(signalTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000322 }
323 }
324 displayData.gpuEndFenceTime = std::move(fenceTime);
Matt Buckley2fa85012022-08-30 22:38:45 +0000325 displayData.gpuStartTime = TimePoint::now();
Matt Buckley50c44062022-01-17 20:48:10 +0000326}
327
Matt Buckley2fa85012022-08-30 22:38:45 +0000328void PowerAdvisor::setHwcValidateTiming(DisplayId displayId, TimePoint validateStartTime,
329 TimePoint validateEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000330 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000331 displayData.hwcValidateStartTime = validateStartTime;
332 displayData.hwcValidateEndTime = validateEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000333}
334
Matt Buckley2fa85012022-08-30 22:38:45 +0000335void PowerAdvisor::setHwcPresentTiming(DisplayId displayId, TimePoint presentStartTime,
336 TimePoint presentEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000337 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000338 displayData.hwcPresentStartTime = presentStartTime;
339 displayData.hwcPresentEndTime = presentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000340}
341
342void PowerAdvisor::setSkippedValidate(DisplayId displayId, bool skipped) {
343 mDisplayTimingData[displayId].skippedValidate = skipped;
344}
345
346void PowerAdvisor::setRequiresClientComposition(DisplayId displayId,
347 bool requiresClientComposition) {
348 mDisplayTimingData[displayId].usedClientComposition = requiresClientComposition;
349}
350
Matt Buckley2fa85012022-08-30 22:38:45 +0000351void PowerAdvisor::setExpectedPresentTime(TimePoint expectedPresentTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000352 mExpectedPresentTimes.append(expectedPresentTime);
353}
354
Matt Buckley2fa85012022-08-30 22:38:45 +0000355void PowerAdvisor::setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) {
Matt Buckley1809d902022-08-05 06:51:43 +0000356 mLastSfPresentEndTime = presentEndTime;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700357 mLastPresentFenceTime = presentFenceTime;
358}
359
Matt Buckley2fa85012022-08-30 22:38:45 +0000360void PowerAdvisor::setFrameDelay(Duration frameDelayDuration) {
Matt Buckley50c44062022-01-17 20:48:10 +0000361 mFrameDelayDuration = frameDelayDuration;
362}
363
Matt Buckley2fa85012022-08-30 22:38:45 +0000364void PowerAdvisor::setHwcPresentDelayedTime(DisplayId displayId, TimePoint earliestFrameStartTime) {
365 mDisplayTimingData[displayId].hwcPresentDelayedTime = earliestFrameStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000366}
367
Matt Buckley2fa85012022-08-30 22:38:45 +0000368void PowerAdvisor::setCommitStart(TimePoint commitStartTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000369 mCommitStartTimes.append(commitStartTime);
370}
371
Matt Buckley2fa85012022-08-30 22:38:45 +0000372void PowerAdvisor::setCompositeEnd(TimePoint compositeEndTime) {
373 mLastPostcompDuration = compositeEndTime - mLastSfPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000374}
375
376void PowerAdvisor::setDisplays(std::vector<DisplayId>& displayIds) {
377 mDisplayIds = displayIds;
378}
379
Matt Buckley2fa85012022-08-30 22:38:45 +0000380void PowerAdvisor::setTotalFrameTargetWorkDuration(Duration targetDuration) {
Matt Buckley50c44062022-01-17 20:48:10 +0000381 mTotalFrameTargetDuration = targetDuration;
382}
383
384std::vector<DisplayId> PowerAdvisor::getOrderedDisplayIds(
Matt Buckley2fa85012022-08-30 22:38:45 +0000385 std::optional<TimePoint> DisplayTimingData::*sortBy) {
Matt Buckley50c44062022-01-17 20:48:10 +0000386 std::vector<DisplayId> sortedDisplays;
387 std::copy_if(mDisplayIds.begin(), mDisplayIds.end(), std::back_inserter(sortedDisplays),
388 [&](DisplayId id) {
389 return mDisplayTimingData.count(id) &&
390 (mDisplayTimingData[id].*sortBy).has_value();
391 });
392 std::sort(sortedDisplays.begin(), sortedDisplays.end(), [&](DisplayId idA, DisplayId idB) {
393 return *(mDisplayTimingData[idA].*sortBy) < *(mDisplayTimingData[idB].*sortBy);
394 });
395 return sortedDisplays;
396}
397
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000398std::optional<Duration> PowerAdvisor::estimateWorkDuration() {
399 if (!mExpectedPresentTimes.isFull() || !mCommitStartTimes.isFull()) {
Matt Buckley50c44062022-01-17 20:48:10 +0000400 return std::nullopt;
401 }
402
403 // Tracks when we finish presenting to hwc
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000404 TimePoint estimatedHwcEndTime = mCommitStartTimes[0];
Matt Buckley50c44062022-01-17 20:48:10 +0000405
406 // How long we spent this frame not doing anything, waiting for fences or vsync
Matt Buckley2fa85012022-08-30 22:38:45 +0000407 Duration idleDuration = 0ns;
Matt Buckley50c44062022-01-17 20:48:10 +0000408
409 // Most recent previous gpu end time in the current frame, probably from a prior display, used
410 // 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 +0000411 std::optional<TimePoint> previousValidGpuEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000412
413 // The currently estimated gpu end time for the frame,
414 // used to accumulate gpu time as we iterate over the active displays
Matt Buckley2fa85012022-08-30 22:38:45 +0000415 std::optional<TimePoint> estimatedGpuEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000416
Matt Buckley50c44062022-01-17 20:48:10 +0000417 // The timing info for the previously calculated display, if there was one
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000418 std::optional<DisplayTimeline> previousDisplayTiming;
Matt Buckley50c44062022-01-17 20:48:10 +0000419 std::vector<DisplayId>&& displayIds =
Matt Buckley16dec1f2022-06-07 21:46:20 +0000420 getOrderedDisplayIds(&DisplayTimingData::hwcPresentStartTime);
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000421 DisplayTimeline displayTiming;
Matt Buckley50c44062022-01-17 20:48:10 +0000422
Matt Buckley1809d902022-08-05 06:51:43 +0000423 // Iterate over the displays that use hwc in the same order they are presented
Matt Buckley50c44062022-01-17 20:48:10 +0000424 for (DisplayId displayId : displayIds) {
425 if (mDisplayTimingData.count(displayId) == 0) {
426 continue;
427 }
428
429 auto& displayData = mDisplayTimingData.at(displayId);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700430
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000431 displayTiming = displayData.calculateDisplayTimeline(mLastPresentFenceTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000432
Matt Buckley16dec1f2022-06-07 21:46:20 +0000433 // If this is the first display, include the duration before hwc present starts
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000434 if (!previousDisplayTiming.has_value()) {
435 estimatedHwcEndTime += displayTiming.hwcPresentStartTime - mCommitStartTimes[0];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000436 } else { // Otherwise add the time since last display's hwc present finished
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000437 estimatedHwcEndTime +=
438 displayTiming.hwcPresentStartTime - previousDisplayTiming->hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000439 }
440
Matt Buckley50c44062022-01-17 20:48:10 +0000441 // Update predicted present finish time with this display's present time
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000442 estimatedHwcEndTime = displayTiming.hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000443
444 // Track how long we spent waiting for the fence, can be excluded from the timing estimate
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000445 idleDuration += displayTiming.probablyWaitsForPresentFence
446 ? mLastPresentFenceTime - displayTiming.presentFenceWaitStartTime
Matt Buckley2fa85012022-08-30 22:38:45 +0000447 : 0ns;
Matt Buckley50c44062022-01-17 20:48:10 +0000448
449 // Track how long we spent waiting to present, can be excluded from the timing estimate
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000450 idleDuration += displayTiming.hwcPresentDelayDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000451
452 // Estimate the reference frame's gpu timing
453 auto gpuTiming = displayData.estimateGpuTiming(previousValidGpuEndTime);
454 if (gpuTiming.has_value()) {
455 previousValidGpuEndTime = gpuTiming->startTime + gpuTiming->duration;
456
457 // Estimate the prediction frame's gpu end time from the reference frame
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000458 estimatedGpuEndTime = std::max(displayTiming.hwcPresentStartTime,
Matt Buckley2fa85012022-08-30 22:38:45 +0000459 estimatedGpuEndTime.value_or(TimePoint{0ns})) +
Matt Buckley50c44062022-01-17 20:48:10 +0000460 gpuTiming->duration;
461 }
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000462 previousDisplayTiming = displayTiming;
Matt Buckley50c44062022-01-17 20:48:10 +0000463 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000464 ATRACE_INT64("Idle duration", idleDuration.ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000465
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000466 TimePoint estimatedFlingerEndTime = mLastSfPresentEndTime;
Matt Buckley1809d902022-08-05 06:51:43 +0000467
Matt Buckley50c44062022-01-17 20:48:10 +0000468 // Don't count time spent idly waiting in the estimate as we could do more work in that time
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000469 estimatedHwcEndTime -= idleDuration;
Matt Buckley1809d902022-08-05 06:51:43 +0000470 estimatedFlingerEndTime -= idleDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000471
472 // We finish the frame when both present and the gpu are done, so wait for the later of the two
473 // Also add the frame delay duration since the target did not move while we were delayed
Matt Buckley2fa85012022-08-30 22:38:45 +0000474 Duration totalDuration = mFrameDelayDuration +
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000475 std::max(estimatedHwcEndTime, estimatedGpuEndTime.value_or(TimePoint{0ns})) -
Matt Buckley2fa85012022-08-30 22:38:45 +0000476 mCommitStartTimes[0];
Matt Buckley50c44062022-01-17 20:48:10 +0000477
478 // We finish SurfaceFlinger when post-composition finishes, so add that in here
Matt Buckley2fa85012022-08-30 22:38:45 +0000479 Duration flingerDuration =
Matt Buckley1809d902022-08-05 06:51:43 +0000480 estimatedFlingerEndTime + mLastPostcompDuration - mCommitStartTimes[0];
481
482 // Combine the two timings into a single normalized one
Matt Buckley2fa85012022-08-30 22:38:45 +0000483 Duration combinedDuration = combineTimingEstimates(totalDuration, flingerDuration);
Matt Buckley50c44062022-01-17 20:48:10 +0000484
485 return std::make_optional(combinedDuration);
486}
487
Matt Buckley2fa85012022-08-30 22:38:45 +0000488Duration PowerAdvisor::combineTimingEstimates(Duration totalDuration, Duration flingerDuration) {
489 Duration targetDuration{0ns};
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000490 targetDuration = mTargetDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000491 if (!mTotalFrameTargetDuration.has_value()) return flingerDuration;
492
493 // Normalize total to the flinger target (vsync period) since that's how often we actually send
494 // hints
Matt Buckley2fa85012022-08-30 22:38:45 +0000495 Duration normalizedTotalDuration = Duration::fromNs((targetDuration.ns() * totalDuration.ns()) /
496 mTotalFrameTargetDuration->ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000497 return std::max(flingerDuration, normalizedTotalDuration);
498}
499
Matt Buckley50c44062022-01-17 20:48:10 +0000500PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimingData::calculateDisplayTimeline(
Matt Buckley2fa85012022-08-30 22:38:45 +0000501 TimePoint fenceTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000502 DisplayTimeline timeline;
Matt Buckley16dec1f2022-06-07 21:46:20 +0000503 // How long between calling hwc present and trying to wait on the fence
Matt Buckley2fa85012022-08-30 22:38:45 +0000504 const Duration fenceWaitStartDelay =
505 (skippedValidate ? kFenceWaitStartDelaySkippedValidate : kFenceWaitStartDelayValidated);
Matt Buckley50c44062022-01-17 20:48:10 +0000506
Matt Buckley16dec1f2022-06-07 21:46:20 +0000507 // Did our reference frame wait for an appropriate vsync before calling into hwc
508 const bool waitedOnHwcPresentTime = hwcPresentDelayedTime.has_value() &&
509 *hwcPresentDelayedTime > *hwcPresentStartTime &&
510 *hwcPresentDelayedTime < *hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000511
512 // Use validate start here if we skipped it because we did validate + present together
Matt Buckley16dec1f2022-06-07 21:46:20 +0000513 timeline.hwcPresentStartTime = skippedValidate ? *hwcValidateStartTime : *hwcPresentStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000514
515 // Use validate end here if we skipped it because we did validate + present together
Matt Buckley16dec1f2022-06-07 21:46:20 +0000516 timeline.hwcPresentEndTime = skippedValidate ? *hwcValidateEndTime : *hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000517
Matt Buckley16dec1f2022-06-07 21:46:20 +0000518 // How long hwc present was delayed waiting for the next appropriate vsync
519 timeline.hwcPresentDelayDuration =
Matt Buckley2fa85012022-08-30 22:38:45 +0000520 (waitedOnHwcPresentTime ? *hwcPresentDelayedTime - *hwcPresentStartTime : 0ns);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700521 // When we started waiting for the present fence after calling into hwc present
522 timeline.presentFenceWaitStartTime =
Matt Buckley16dec1f2022-06-07 21:46:20 +0000523 timeline.hwcPresentStartTime + timeline.hwcPresentDelayDuration + fenceWaitStartDelay;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700524 timeline.probablyWaitsForPresentFence = fenceTime > timeline.presentFenceWaitStartTime &&
Matt Buckley16dec1f2022-06-07 21:46:20 +0000525 fenceTime < timeline.hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000526
Matt Buckley16dec1f2022-06-07 21:46:20 +0000527 // How long we ran after we finished waiting for the fence but before hwc present finished
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700528 timeline.postPresentFenceHwcPresentDuration = timeline.hwcPresentEndTime -
529 (timeline.probablyWaitsForPresentFence ? fenceTime
530 : timeline.presentFenceWaitStartTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000531 return timeline;
532}
533
534std::optional<PowerAdvisor::GpuTimeline> PowerAdvisor::DisplayTimingData::estimateGpuTiming(
Matt Buckley2fa85012022-08-30 22:38:45 +0000535 std::optional<TimePoint> previousEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000536 if (!(usedClientComposition && lastValidGpuStartTime.has_value() && gpuEndFenceTime)) {
537 return std::nullopt;
538 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000539 const TimePoint latestGpuStartTime =
540 std::max(previousEndTime.value_or(TimePoint{0ns}), *gpuStartTime);
541 const nsecs_t gpuEndFenceSignal = gpuEndFenceTime->getSignalTime();
542 Duration gpuDuration{0ns};
543 if (gpuEndFenceSignal != Fence::SIGNAL_TIME_INVALID &&
544 gpuEndFenceSignal != Fence::SIGNAL_TIME_PENDING) {
545 const TimePoint latestGpuEndTime = TimePoint::fromNs(gpuEndFenceSignal);
546
Matt Buckley50c44062022-01-17 20:48:10 +0000547 // If we know how long the most recent gpu duration was, use that
548 gpuDuration = latestGpuEndTime - latestGpuStartTime;
549 } else if (lastValidGpuEndTime.has_value()) {
550 // If we don't have the fence data, use the most recent information we do have
551 gpuDuration = *lastValidGpuEndTime - *lastValidGpuStartTime;
Matt Buckley2fa85012022-08-30 22:38:45 +0000552 if (gpuEndFenceSignal == Fence::SIGNAL_TIME_PENDING) {
Matt Buckley50c44062022-01-17 20:48:10 +0000553 // If pending but went over the previous duration, use current time as the end
Matt Buckley2fa85012022-08-30 22:38:45 +0000554 gpuDuration = std::max(gpuDuration, Duration{TimePoint::now() - latestGpuStartTime});
Matt Buckley50c44062022-01-17 20:48:10 +0000555 }
556 }
557 return GpuTimeline{.duration = gpuDuration, .startTime = latestGpuStartTime};
558}
559
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000560const bool PowerAdvisor::sTraceHintSessionData =
Matt Buckleyef51fba2021-10-12 19:30:12 +0000561 base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
562
Matt Buckleyeae1e252023-02-28 06:51:28 +0000563const Duration PowerAdvisor::sTargetSafetyMargin = std::chrono::microseconds(
564 base::GetIntProperty<int64_t>("debug.sf.hint_margin_us",
565 ticks<std::micro>(PowerAdvisor::kDefaultTargetSafetyMargin)));
566
Matt Buckleycbfe23c2022-11-08 23:12:04 +0000567power::PowerHalController& PowerAdvisor::getPowerHal() {
568 static std::once_flag halFlag;
569 std::call_once(halFlag, [this] { mPowerHal->init(); });
570 return *mPowerHal;
Michael Wright1509a232018-06-21 02:50:34 +0100571}
572
573} // namespace impl
574} // namespace Hwc2
575} // namespace android