blob: c914ec306664bbdf1db2da98027c005214254053 [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>
Vishnu Nairbe0ad902024-06-27 23:38:43 +000030#include <common/trace.h>
Michael Wright1509a232018-06-21 02:50:34 +010031#include <utils/Log.h>
32#include <utils/Mutex.h>
33
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 Wang154fc042024-04-02 14:17:53 -070049using aidl::android::hardware::power::ChannelConfig;
Xiang Wang99f6f3c2023-05-22 13:12:16 -070050using aidl::android::hardware::power::Mode;
51using aidl::android::hardware::power::SessionHint;
Matt Buckley52dfaad2024-03-07 20:20:07 +000052using aidl::android::hardware::power::SessionTag;
Xiang Wang99f6f3c2023-05-22 13:12:16 -070053using aidl::android::hardware::power::WorkDuration;
Xiang Wang154fc042024-04-02 14:17:53 -070054using aidl::android::hardware::power::WorkDurationFixedV1;
55
56using aidl::android::hardware::common::fmq::MQDescriptor;
57using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
58using aidl::android::hardware::power::ChannelMessage;
59using android::hardware::EventFlag;
60
61using ChannelMessageContents = ChannelMessage::ChannelMessageContents;
62using MsgQueue = android::AidlMessageQueue<ChannelMessage, SynchronizedReadWrite>;
63using FlagQueue = android::AidlMessageQueue<int8_t, SynchronizedReadWrite>;
Matt Buckley06f299a2021-09-24 19:43:51 +000064
Michael Wright1509a232018-06-21 02:50:34 +010065PowerAdvisor::~PowerAdvisor() = default;
66
Dan Stoza030fbc12020-02-19 15:32:01 -080067namespace {
Alec Mouri29382ad2022-05-11 18:38:38 +000068std::chrono::milliseconds getUpdateTimeout() {
Dan Stoza030fbc12020-02-19 15:32:01 -080069 // Default to a timeout of 80ms if nothing else is specified
Alec Mouri29382ad2022-05-11 18:38:38 +000070 static std::chrono::milliseconds timeout =
71 std::chrono::milliseconds(sysprop::display_update_imminent_timeout_ms(80));
Dan Stoza030fbc12020-02-19 15:32:01 -080072 return timeout;
73}
74
Ady Abrahamabce1652022-02-24 10:51:19 -080075void traceExpensiveRendering(bool enabled) {
76 if (enabled) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +000077 SFTRACE_ASYNC_BEGIN("ExpensiveRendering", 0);
Ady Abrahamabce1652022-02-24 10:51:19 -080078 } else {
Vishnu Nairbe0ad902024-06-27 23:38:43 +000079 SFTRACE_ASYNC_END("ExpensiveRendering", 0);
Ady Abrahamabce1652022-02-24 10:51:19 -080080 }
81}
82
Dan Stoza030fbc12020-02-19 15:32:01 -080083} // namespace
84
Matt Buckley0538cae2022-11-08 23:12:04 +000085PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger)
86 : mPowerHal(std::make_unique<power::PowerHalController>()), mFlinger(flinger) {
Alec Mouri29382ad2022-05-11 18:38:38 +000087 if (getUpdateTimeout() > 0ms) {
88 mScreenUpdateTimer.emplace("UpdateImminentTimer", getUpdateTimeout(),
Alec Mouric059dcf2022-05-05 23:40:07 +000089 /* resetCallback */ nullptr,
90 /* timeoutCallback */
91 [this] {
Alec Mouri29382ad2022-05-11 18:38:38 +000092 while (true) {
93 auto timeSinceLastUpdate = std::chrono::nanoseconds(
94 systemTime() - mLastScreenUpdatedTime.load());
95 if (timeSinceLastUpdate >= getUpdateTimeout()) {
96 break;
97 }
Alec Mouric059dcf2022-05-05 23:40:07 +000098 // We may try to disable expensive rendering and allow
99 // for sending DISPLAY_UPDATE_IMMINENT hints too early if
100 // we idled very shortly after updating the screen, so
101 // make sure we wait enough time.
Alec Mouri29382ad2022-05-11 18:38:38 +0000102 std::this_thread::sleep_for(getUpdateTimeout() -
103 timeSinceLastUpdate);
Alec Mouric059dcf2022-05-05 23:40:07 +0000104 }
105 mSendUpdateImminent.store(true);
106 mFlinger.disableExpensiveRendering();
107 });
108 }
109}
Alec Mouridea1ac52021-06-23 18:12:18 -0700110
111void PowerAdvisor::init() {
112 // Defer starting the screen update timer until SurfaceFlinger finishes construction.
Alec Mouric059dcf2022-05-05 23:40:07 +0000113 if (mScreenUpdateTimer) {
114 mScreenUpdateTimer->start();
Dan Stoza030fbc12020-02-19 15:32:01 -0800115 }
116}
Michael Wright1509a232018-06-21 02:50:34 +0100117
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700118void PowerAdvisor::onBootFinished() {
119 mBootFinished.store(true);
120}
121
Peiyong Lin74ca2f42019-01-14 19:36:57 -0800122void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000123 if (!mHasExpensiveRendering) {
124 ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
125 return;
126 }
Michael Wright1509a232018-06-21 02:50:34 +0100127 if (expected) {
128 mExpensiveDisplays.insert(displayId);
129 } else {
130 mExpensiveDisplays.erase(displayId);
131 }
132
Michael Wright1509a232018-06-21 02:50:34 +0100133 const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
134 if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000135 auto ret = getPowerHal().setMode(Mode::EXPENSIVE_RENDERING, expectsExpensiveRendering);
136 if (!ret.isOk()) {
137 if (ret.isUnsupported()) {
138 mHasExpensiveRendering = false;
139 }
Michael Wright1509a232018-06-21 02:50:34 +0100140 return;
141 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800142
Michael Wright1509a232018-06-21 02:50:34 +0100143 mNotifiedExpensiveRendering = expectsExpensiveRendering;
Matt Buckley0538cae2022-11-08 23:12:04 +0000144 traceExpensiveRendering(mNotifiedExpensiveRendering);
Michael Wright1509a232018-06-21 02:50:34 +0100145 }
146}
147
jimmyshiu4e211772023-06-15 15:18:38 +0000148void PowerAdvisor::notifyCpuLoadUp() {
149 // Only start sending this notification once the system has booted so we don't introduce an
150 // early-boot dependency on Power HAL
151 if (!mBootFinished.load()) {
152 return;
153 }
Xiang Wang154fc042024-04-02 14:17:53 -0700154 sendHintSessionHint(SessionHint::CPU_LOAD_UP);
jimmyshiu4e211772023-06-15 15:18:38 +0000155}
156
Matt Buckley15ecd1c2022-11-01 21:57:16 +0000157void PowerAdvisor::notifyDisplayUpdateImminentAndCpuReset() {
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700158 // Only start sending this notification once the system has booted so we don't introduce an
159 // early-boot dependency on Power HAL
160 if (!mBootFinished.load()) {
161 return;
162 }
163
Alec Mouric059dcf2022-05-05 23:40:07 +0000164 if (mSendUpdateImminent.exchange(false)) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000165 ALOGV("AIDL notifyDisplayUpdateImminentAndCpuReset");
Xiang Wang154fc042024-04-02 14:17:53 -0700166 sendHintSessionHint(SessionHint::CPU_LOAD_RESET);
Dan Stoza030fbc12020-02-19 15:32:01 -0800167
Matt Buckley0538cae2022-11-08 23:12:04 +0000168 if (!mHasDisplayUpdateImminent) {
169 ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
170 } else {
171 auto ret = getPowerHal().setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
172 if (ret.isUnsupported()) {
173 mHasDisplayUpdateImminent = false;
174 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800175 }
Alec Mouric059dcf2022-05-05 23:40:07 +0000176
177 if (mScreenUpdateTimer) {
178 mScreenUpdateTimer->reset();
179 } else {
180 // If we don't have a screen update timer, then we don't throttle power hal calls so
181 // flip this bit back to allow for calling into power hal again.
182 mSendUpdateImminent.store(true);
183 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800184 }
185
Alec Mouric059dcf2022-05-05 23:40:07 +0000186 if (mScreenUpdateTimer) {
187 mLastScreenUpdatedTime.store(systemTime());
Dan Stoza030fbc12020-02-19 15:32:01 -0800188 }
189}
190
Matt Buckley06f299a2021-09-24 19:43:51 +0000191bool PowerAdvisor::usePowerHintSession() {
192 // uses cached value since the underlying support and flag are unlikely to change at runtime
Matt Buckley0538cae2022-11-08 23:12:04 +0000193 return mHintSessionEnabled.value_or(false) && supportsPowerHintSession();
Matt Buckley06f299a2021-09-24 19:43:51 +0000194}
195
196bool PowerAdvisor::supportsPowerHintSession() {
Matt Buckley0538cae2022-11-08 23:12:04 +0000197 if (!mSupportsHintSession.has_value()) {
198 mSupportsHintSession = getPowerHal().getHintSessionPreferredRate().isOk();
Matt Buckley06f299a2021-09-24 19:43:51 +0000199 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000200 return *mSupportsHintSession;
Matt Buckley06f299a2021-09-24 19:43:51 +0000201}
202
Matt Buckley52dfaad2024-03-07 20:20:07 +0000203bool PowerAdvisor::shouldCreateSessionWithConfig() {
Xiang Wangcb50bbd2024-04-18 16:57:54 -0700204 return mSessionConfigSupported && mBootFinished &&
205 FlagManager::getInstance().adpf_use_fmq_channel();
Matt Buckley52dfaad2024-03-07 20:20:07 +0000206}
207
Xiang Wang154fc042024-04-02 14:17:53 -0700208void PowerAdvisor::sendHintSessionHint(SessionHint hint) {
209 if (!mBootFinished || !usePowerHintSession()) {
210 ALOGV("Power hint session is not enabled, skip sending session hint");
211 return;
212 }
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000213 SFTRACE_CALL();
Vishnu Nair2665ca92024-07-09 22:08:15 +0000214 if (sTraceHintSessionData) SFTRACE_INT("Session hint", static_cast<int>(hint));
Xiang Wang154fc042024-04-02 14:17:53 -0700215 {
216 std::scoped_lock lock(mHintSessionMutex);
217 if (!ensurePowerHintSessionRunning()) {
218 ALOGV("Hint session not running and could not be started, skip sending session hint");
219 return;
220 }
221 ALOGV("Sending session hint: %d", static_cast<int>(hint));
222 if (!writeHintSessionMessage<ChannelMessageContents::Tag::hint>(&hint, 1)) {
223 auto ret = mHintSession->sendHint(hint);
224 if (!ret.isOk()) {
225 ALOGW("Failed to send session hint with error: %s", ret.errorMessage());
226 mHintSession = nullptr;
227 }
228 }
229 }
230}
231
Matt Buckley0538cae2022-11-08 23:12:04 +0000232bool PowerAdvisor::ensurePowerHintSessionRunning() {
Matt Buckley547cc0c2023-10-27 22:22:36 +0000233 if (mHintSession == nullptr && !mHintSessionThreadIds.empty() && usePowerHintSession()) {
Matt Buckley52dfaad2024-03-07 20:20:07 +0000234 if (shouldCreateSessionWithConfig()) {
235 auto ret = getPowerHal().createHintSessionWithConfig(getpid(),
236 static_cast<int32_t>(getuid()),
237 mHintSessionThreadIds,
238 mTargetDuration.ns(),
239 SessionTag::SURFACEFLINGER,
240 &mSessionConfig);
241 if (ret.isOk()) {
242 mHintSession = ret.value();
Matt Buckley48eb4352024-10-18 11:48:46 -0700243 if (FlagManager::getInstance().adpf_use_fmq_channel_fixed() &&
244 FlagManager::getInstance().adpf_fmq_sf()) {
Xiang Wang154fc042024-04-02 14:17:53 -0700245 setUpFmq();
246 }
Matt Buckley52dfaad2024-03-07 20:20:07 +0000247 }
248 // If it fails the first time we try, or ever returns unsupported, assume unsupported
249 else if (mFirstConfigSupportCheck || ret.isUnsupported()) {
250 ALOGI("Hint session with config is unsupported, falling back to a legacy session");
251 mSessionConfigSupported = false;
252 }
253 mFirstConfigSupportCheck = false;
254 }
255 // Immediately try original method after, in case the first way returned unsupported
256 if (mHintSession == nullptr && !shouldCreateSessionWithConfig()) {
257 auto ret = getPowerHal().createHintSession(getpid(), static_cast<int32_t>(getuid()),
258 mHintSessionThreadIds, mTargetDuration.ns());
259 if (ret.isOk()) {
260 mHintSession = ret.value();
261 }
Matt Buckley547cc0c2023-10-27 22:22:36 +0000262 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000263 }
Matt Buckley547cc0c2023-10-27 22:22:36 +0000264 return mHintSession != nullptr;
Matt Buckley06f299a2021-09-24 19:43:51 +0000265}
266
Xiang Wang154fc042024-04-02 14:17:53 -0700267void PowerAdvisor::setUpFmq() {
268 auto&& channelRet = getPowerHal().getSessionChannel(getpid(), static_cast<int32_t>(getuid()));
269 if (!channelRet.isOk()) {
270 ALOGE("Failed to get session channel with error: %s", channelRet.errorMessage());
271 return;
272 }
273 auto& channelConfig = channelRet.value();
274 mMsgQueue = std::make_unique<MsgQueue>(std::move(channelConfig.channelDescriptor), true);
275 LOG_ALWAYS_FATAL_IF(!mMsgQueue->isValid(), "Failed to set up hint session msg queue");
276 LOG_ALWAYS_FATAL_IF(channelConfig.writeFlagBitmask <= 0,
277 "Invalid flag bit masks found in channel config: writeBitMask(%d)",
278 channelConfig.writeFlagBitmask);
279 mFmqWriteMask = static_cast<uint32_t>(channelConfig.writeFlagBitmask);
280 if (!channelConfig.eventFlagDescriptor.has_value()) {
281 // For FMQ v1 in Android 15 we will force using shared event flag since the default
282 // no-op FMQ impl in Power HAL v5 will always return a valid channel config with
283 // non-zero masks but no shared flag.
284 mMsgQueue = nullptr;
285 ALOGE("No event flag descriptor found in channel config");
286 return;
287 }
288 mFlagQueue = std::make_unique<FlagQueue>(std::move(*channelConfig.eventFlagDescriptor), true);
289 LOG_ALWAYS_FATAL_IF(!mFlagQueue->isValid(), "Failed to set up hint session flag queue");
290 auto status = EventFlag::createEventFlag(mFlagQueue->getEventFlagWord(), &mEventFlag);
291 LOG_ALWAYS_FATAL_IF(status != OK, "Failed to set up hint session event flag");
292}
293
Matt Buckley0538cae2022-11-08 23:12:04 +0000294void PowerAdvisor::updateTargetWorkDuration(Duration targetDuration) {
Xiang Wangcb50bbd2024-04-18 16:57:54 -0700295 if (!mBootFinished || !usePowerHintSession()) {
Xiang Wang154fc042024-04-02 14:17:53 -0700296 ALOGV("Power hint session is not enabled, skipping target update");
Matt Buckley06f299a2021-09-24 19:43:51 +0000297 return;
298 }
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000299 SFTRACE_CALL();
Matt Buckley06f299a2021-09-24 19:43:51 +0000300 {
Matt Buckley0538cae2022-11-08 23:12:04 +0000301 mTargetDuration = targetDuration;
Vishnu Nair2665ca92024-07-09 22:08:15 +0000302 if (sTraceHintSessionData) SFTRACE_INT64("Time target", targetDuration.ns());
Matt Buckley547cc0c2023-10-27 22:22:36 +0000303 if (targetDuration == mLastTargetDurationSent) return;
Xiang Wang154fc042024-04-02 14:17:53 -0700304 std::scoped_lock lock(mHintSessionMutex);
305 if (!ensurePowerHintSessionRunning()) {
306 ALOGV("Hint session not running and could not be started, skip updating target");
307 return;
308 }
309 ALOGV("Sending target time: %" PRId64 "ns", targetDuration.ns());
310 mLastTargetDurationSent = targetDuration;
311 auto target = targetDuration.ns();
312 if (!writeHintSessionMessage<ChannelMessageContents::Tag::targetDuration>(&target, 1)) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000313 auto ret = mHintSession->updateTargetWorkDuration(targetDuration.ns());
314 if (!ret.isOk()) {
315 ALOGW("Failed to set power hint target work duration with error: %s",
Matt Buckley6c18e6d2024-02-07 23:39:50 +0000316 ret.errorMessage());
Matt Buckley547cc0c2023-10-27 22:22:36 +0000317 mHintSession = nullptr;
Matt Buckley0538cae2022-11-08 23:12:04 +0000318 }
Matt Buckley06f299a2021-09-24 19:43:51 +0000319 }
320 }
321}
322
Matt Buckley0538cae2022-11-08 23:12:04 +0000323void PowerAdvisor::reportActualWorkDuration() {
Matt Buckley676e4392023-05-25 22:09:26 +0000324 if (!mBootFinished || !sUseReportActualDuration || !usePowerHintSession()) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000325 ALOGV("Actual work duration power hint cannot be sent, skipping");
326 return;
327 }
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000328 SFTRACE_CALL();
Xiang Wangaab31162024-03-12 19:48:08 -0700329 std::optional<WorkDuration> actualDuration = estimateWorkDuration();
330 if (!actualDuration.has_value() || actualDuration->durationNanos < 0) {
Matt Buckley0538cae2022-11-08 23:12:04 +0000331 ALOGV("Failed to send actual work duration, skipping");
Matt Buckley50c44062022-01-17 20:48:10 +0000332 return;
333 }
Xiang Wangaab31162024-03-12 19:48:08 -0700334 actualDuration->durationNanos += sTargetSafetyMargin.ns();
Matt Buckley0538cae2022-11-08 23:12:04 +0000335 if (sTraceHintSessionData) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000336 SFTRACE_INT64("Measured duration", actualDuration->durationNanos);
337 SFTRACE_INT64("Target error term", actualDuration->durationNanos - mTargetDuration.ns());
338 SFTRACE_INT64("Reported duration", actualDuration->durationNanos);
Xiang Wangcb50bbd2024-04-18 16:57:54 -0700339 if (supportsGpuReporting()) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000340 SFTRACE_INT64("Reported cpu duration", actualDuration->cpuDurationNanos);
341 SFTRACE_INT64("Reported gpu duration", actualDuration->gpuDurationNanos);
Xiang Wangaab31162024-03-12 19:48:08 -0700342 }
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000343 SFTRACE_INT64("Reported target", mLastTargetDurationSent.ns());
344 SFTRACE_INT64("Reported target error term",
345 actualDuration->durationNanos - mLastTargetDurationSent.ns());
Matt Buckley0538cae2022-11-08 23:12:04 +0000346 }
347
Xiang Wangaab31162024-03-12 19:48:08 -0700348 ALOGV("Sending actual work duration of: %" PRId64 " with cpu: %" PRId64 " and gpu: %" PRId64
349 " on reported target: %" PRId64 " with error: %" PRId64,
350 actualDuration->durationNanos, actualDuration->cpuDurationNanos,
351 actualDuration->gpuDurationNanos, mLastTargetDurationSent.ns(),
352 actualDuration->durationNanos - mLastTargetDurationSent.ns());
Matt Buckley0538cae2022-11-08 23:12:04 +0000353
Matt Buckley547cc0c2023-10-27 22:22:36 +0000354 if (mTimingTestingMode) {
355 mDelayReportActualMutexAcquisitonPromise.get_future().wait();
356 mDelayReportActualMutexAcquisitonPromise = std::promise<bool>{};
357 }
358
Matt Buckley0538cae2022-11-08 23:12:04 +0000359 {
Xiang Wang154fc042024-04-02 14:17:53 -0700360 std::scoped_lock lock(mHintSessionMutex);
Matt Buckley547cc0c2023-10-27 22:22:36 +0000361 if (!ensurePowerHintSessionRunning()) {
Xiang Wang154fc042024-04-02 14:17:53 -0700362 ALOGV("Hint session not running and could not be started, skip reporting durations");
Matt Buckley547cc0c2023-10-27 22:22:36 +0000363 return;
364 }
Xiang Wangaab31162024-03-12 19:48:08 -0700365 mHintSessionQueue.push_back(*actualDuration);
Xiang Wang154fc042024-04-02 14:17:53 -0700366 if (!writeHintSessionMessage<
367 ChannelMessageContents::Tag::workDuration>(mHintSessionQueue.data(),
368 mHintSessionQueue.size())) {
369 auto ret = mHintSession->reportActualWorkDuration(mHintSessionQueue);
370 if (!ret.isOk()) {
371 ALOGW("Failed to report actual work durations with error: %s", ret.errorMessage());
372 mHintSession = nullptr;
373 return;
374 }
Matt Buckley50c44062022-01-17 20:48:10 +0000375 }
376 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000377 mHintSessionQueue.clear();
Matt Buckley50c44062022-01-17 20:48:10 +0000378}
379
Xiang Wang154fc042024-04-02 14:17:53 -0700380template <ChannelMessage::ChannelMessageContents::Tag T, class In>
381bool PowerAdvisor::writeHintSessionMessage(In* contents, size_t count) {
382 if (!mMsgQueue) {
383 ALOGV("Skip using FMQ with message tag %hhd as it's not supported", T);
384 return false;
385 }
386 auto availableSize = mMsgQueue->availableToWrite();
387 if (availableSize < count) {
388 ALOGW("Skip using FMQ with message tag %hhd as there isn't enough space", T);
389 return false;
390 }
391 MsgQueue::MemTransaction tx;
392 if (!mMsgQueue->beginWrite(count, &tx)) {
393 ALOGW("Failed to begin writing message with tag %hhd", T);
394 return false;
395 }
396 for (size_t i = 0; i < count; ++i) {
397 if constexpr (T == ChannelMessageContents::Tag::workDuration) {
398 const WorkDuration& duration = contents[i];
399 new (tx.getSlot(i)) ChannelMessage{
400 .sessionID = static_cast<int32_t>(mSessionConfig.id),
401 .timeStampNanos =
402 (i == count - 1) ? ::android::uptimeNanos() : duration.timeStampNanos,
403 .data = ChannelMessageContents::make<ChannelMessageContents::Tag::workDuration,
404 WorkDurationFixedV1>({
405 .durationNanos = duration.durationNanos,
406 .workPeriodStartTimestampNanos = duration.workPeriodStartTimestampNanos,
407 .cpuDurationNanos = duration.cpuDurationNanos,
408 .gpuDurationNanos = duration.gpuDurationNanos,
409 }),
410 };
411 } else {
412 new (tx.getSlot(i)) ChannelMessage{
413 .sessionID = static_cast<int32_t>(mSessionConfig.id),
414 .timeStampNanos = ::android::uptimeNanos(),
415 .data = ChannelMessageContents::make<T, In>(std::move(contents[i])),
416 };
417 }
418 }
419 if (!mMsgQueue->commitWrite(count)) {
420 ALOGW("Failed to send message with tag %hhd, fall back to binder call", T);
421 return false;
422 }
423 mEventFlag->wake(mFmqWriteMask);
424 return true;
425}
426
Matt Buckley0538cae2022-11-08 23:12:04 +0000427void PowerAdvisor::enablePowerHintSession(bool enabled) {
428 mHintSessionEnabled = enabled;
Matt Buckley06f299a2021-09-24 19:43:51 +0000429}
430
Matt Buckley547cc0c2023-10-27 22:22:36 +0000431bool PowerAdvisor::startPowerHintSession(std::vector<int32_t>&& threadIds) {
432 mHintSessionThreadIds = threadIds;
Matt Buckley0538cae2022-11-08 23:12:04 +0000433 if (!mBootFinished.load()) {
434 return false;
Matt Buckleyef51fba2021-10-12 19:30:12 +0000435 }
Matt Buckley0538cae2022-11-08 23:12:04 +0000436 if (!usePowerHintSession()) {
437 ALOGI("Cannot start power hint session: disabled or unsupported");
438 return false;
439 }
Matt Buckley547cc0c2023-10-27 22:22:36 +0000440 LOG_ALWAYS_FATAL_IF(mHintSessionThreadIds.empty(),
441 "No thread IDs provided to power hint session!");
Xiang Wang154fc042024-04-02 14:17:53 -0700442 {
443 std::scoped_lock lock(mHintSessionMutex);
444 if (mHintSession != nullptr) {
445 ALOGE("Cannot start power hint session: already running");
446 return false;
447 }
448 return ensurePowerHintSessionRunning();
Matt Buckley0538cae2022-11-08 23:12:04 +0000449 }
Matt Buckleyef51fba2021-10-12 19:30:12 +0000450}
451
Xiang Wangcb50bbd2024-04-18 16:57:54 -0700452bool PowerAdvisor::supportsGpuReporting() {
453 return mBootFinished && FlagManager::getInstance().adpf_gpu_sf();
454}
455
Xiang Wangaab31162024-03-12 19:48:08 -0700456void PowerAdvisor::setGpuStartTime(DisplayId displayId, TimePoint startTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000457 DisplayTimingData& displayData = mDisplayTimingData[displayId];
458 if (displayData.gpuEndFenceTime) {
459 nsecs_t signalTime = displayData.gpuEndFenceTime->getSignalTime();
460 if (signalTime != Fence::SIGNAL_TIME_INVALID && signalTime != Fence::SIGNAL_TIME_PENDING) {
Xiang Wangaab31162024-03-12 19:48:08 -0700461 displayData.lastValidGpuStartTime = displayData.gpuStartTime;
462 displayData.lastValidGpuEndTime = TimePoint::fromNs(signalTime);
463 for (auto&& [_, otherDisplayData] : mDisplayTimingData) {
464 if (!otherDisplayData.lastValidGpuStartTime.has_value() ||
465 !otherDisplayData.lastValidGpuEndTime.has_value())
466 continue;
467 if ((*otherDisplayData.lastValidGpuStartTime < *displayData.gpuStartTime) &&
468 (*otherDisplayData.lastValidGpuEndTime > *displayData.gpuStartTime)) {
469 displayData.lastValidGpuStartTime = *otherDisplayData.lastValidGpuEndTime;
470 break;
471 }
472 }
473 }
474 displayData.gpuEndFenceTime = nullptr;
475 }
476 displayData.gpuStartTime = startTime;
477}
478
479void PowerAdvisor::setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime) {
480 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Xiang Wangcb50bbd2024-04-18 16:57:54 -0700481 if (displayData.gpuEndFenceTime && !supportsGpuReporting()) {
Xiang Wangaab31162024-03-12 19:48:08 -0700482 nsecs_t signalTime = displayData.gpuEndFenceTime->getSignalTime();
483 if (signalTime != Fence::SIGNAL_TIME_INVALID && signalTime != Fence::SIGNAL_TIME_PENDING) {
484 displayData.lastValidGpuStartTime = displayData.gpuStartTime;
485 displayData.lastValidGpuEndTime = TimePoint::fromNs(signalTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000486 for (auto&& [_, otherDisplayData] : mDisplayTimingData) {
487 // If the previous display started before us but ended after we should have
488 // started, then it likely delayed our start time and we must compensate for that.
489 // Displays finishing earlier should have already made their way through this call
490 // and swapped their timing into "lastValid" from "latest", so we check that here.
491 if (!otherDisplayData.lastValidGpuStartTime.has_value()) continue;
492 if ((*otherDisplayData.lastValidGpuStartTime < *displayData.gpuStartTime) &&
493 (*otherDisplayData.lastValidGpuEndTime > *displayData.gpuStartTime)) {
494 displayData.lastValidGpuStartTime = *otherDisplayData.lastValidGpuEndTime;
495 break;
496 }
497 }
Matt Buckley50c44062022-01-17 20:48:10 +0000498 }
499 }
500 displayData.gpuEndFenceTime = std::move(fenceTime);
Xiang Wangcb50bbd2024-04-18 16:57:54 -0700501 if (!supportsGpuReporting()) {
Xiang Wangaab31162024-03-12 19:48:08 -0700502 displayData.gpuStartTime = TimePoint::now();
503 }
Matt Buckley50c44062022-01-17 20:48:10 +0000504}
505
Matt Buckley2fa85012022-08-30 22:38:45 +0000506void PowerAdvisor::setHwcValidateTiming(DisplayId displayId, TimePoint validateStartTime,
507 TimePoint validateEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000508 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000509 displayData.hwcValidateStartTime = validateStartTime;
510 displayData.hwcValidateEndTime = validateEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000511}
512
Matt Buckley2fa85012022-08-30 22:38:45 +0000513void PowerAdvisor::setHwcPresentTiming(DisplayId displayId, TimePoint presentStartTime,
514 TimePoint presentEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000515 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000516 displayData.hwcPresentStartTime = presentStartTime;
517 displayData.hwcPresentEndTime = presentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000518}
519
520void PowerAdvisor::setSkippedValidate(DisplayId displayId, bool skipped) {
521 mDisplayTimingData[displayId].skippedValidate = skipped;
522}
523
Xiang Wangaab31162024-03-12 19:48:08 -0700524void PowerAdvisor::setRequiresRenderEngine(DisplayId displayId, bool requiresRenderEngine) {
525 mDisplayTimingData[displayId].requiresRenderEngine = requiresRenderEngine;
Matt Buckley50c44062022-01-17 20:48:10 +0000526}
527
Matt Buckley2fa85012022-08-30 22:38:45 +0000528void PowerAdvisor::setExpectedPresentTime(TimePoint expectedPresentTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000529 mExpectedPresentTimes.append(expectedPresentTime);
530}
531
Matt Buckley2fa85012022-08-30 22:38:45 +0000532void PowerAdvisor::setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) {
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700533 mLastPresentFenceTime = presentFenceTime;
Xiang Wangaab31162024-03-12 19:48:08 -0700534 mLastSfPresentEndTime = presentEndTime;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700535}
536
Matt Buckley2fa85012022-08-30 22:38:45 +0000537void PowerAdvisor::setFrameDelay(Duration frameDelayDuration) {
Matt Buckley50c44062022-01-17 20:48:10 +0000538 mFrameDelayDuration = frameDelayDuration;
539}
540
Matt Buckley2fa85012022-08-30 22:38:45 +0000541void PowerAdvisor::setHwcPresentDelayedTime(DisplayId displayId, TimePoint earliestFrameStartTime) {
542 mDisplayTimingData[displayId].hwcPresentDelayedTime = earliestFrameStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000543}
544
Matt Buckley2fa85012022-08-30 22:38:45 +0000545void PowerAdvisor::setCommitStart(TimePoint commitStartTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000546 mCommitStartTimes.append(commitStartTime);
547}
548
Matt Buckley2fa85012022-08-30 22:38:45 +0000549void PowerAdvisor::setCompositeEnd(TimePoint compositeEndTime) {
550 mLastPostcompDuration = compositeEndTime - mLastSfPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000551}
552
553void PowerAdvisor::setDisplays(std::vector<DisplayId>& displayIds) {
554 mDisplayIds = displayIds;
555}
556
Matt Buckley2fa85012022-08-30 22:38:45 +0000557void PowerAdvisor::setTotalFrameTargetWorkDuration(Duration targetDuration) {
Matt Buckley50c44062022-01-17 20:48:10 +0000558 mTotalFrameTargetDuration = targetDuration;
559}
560
561std::vector<DisplayId> PowerAdvisor::getOrderedDisplayIds(
Matt Buckley2fa85012022-08-30 22:38:45 +0000562 std::optional<TimePoint> DisplayTimingData::*sortBy) {
Matt Buckley50c44062022-01-17 20:48:10 +0000563 std::vector<DisplayId> sortedDisplays;
564 std::copy_if(mDisplayIds.begin(), mDisplayIds.end(), std::back_inserter(sortedDisplays),
565 [&](DisplayId id) {
566 return mDisplayTimingData.count(id) &&
567 (mDisplayTimingData[id].*sortBy).has_value();
568 });
569 std::sort(sortedDisplays.begin(), sortedDisplays.end(), [&](DisplayId idA, DisplayId idB) {
570 return *(mDisplayTimingData[idA].*sortBy) < *(mDisplayTimingData[idB].*sortBy);
571 });
572 return sortedDisplays;
573}
574
Xiang Wangaab31162024-03-12 19:48:08 -0700575std::optional<WorkDuration> PowerAdvisor::estimateWorkDuration() {
Matt Buckley0538cae2022-11-08 23:12:04 +0000576 if (!mExpectedPresentTimes.isFull() || !mCommitStartTimes.isFull()) {
Matt Buckley50c44062022-01-17 20:48:10 +0000577 return std::nullopt;
578 }
579
580 // Tracks when we finish presenting to hwc
Matt Buckley0538cae2022-11-08 23:12:04 +0000581 TimePoint estimatedHwcEndTime = mCommitStartTimes[0];
Matt Buckley50c44062022-01-17 20:48:10 +0000582
583 // How long we spent this frame not doing anything, waiting for fences or vsync
Matt Buckley2fa85012022-08-30 22:38:45 +0000584 Duration idleDuration = 0ns;
Matt Buckley50c44062022-01-17 20:48:10 +0000585
586 // Most recent previous gpu end time in the current frame, probably from a prior display, used
587 // 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 +0000588 std::optional<TimePoint> previousValidGpuEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000589
590 // The currently estimated gpu end time for the frame,
591 // used to accumulate gpu time as we iterate over the active displays
Matt Buckley2fa85012022-08-30 22:38:45 +0000592 std::optional<TimePoint> estimatedGpuEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000593
Matt Buckley50c44062022-01-17 20:48:10 +0000594 std::vector<DisplayId>&& displayIds =
Matt Buckley16dec1f2022-06-07 21:46:20 +0000595 getOrderedDisplayIds(&DisplayTimingData::hwcPresentStartTime);
Matt Buckley0538cae2022-11-08 23:12:04 +0000596 DisplayTimeline displayTiming;
Xiang Wangaab31162024-03-12 19:48:08 -0700597 std::optional<GpuTimeline> firstGpuTimeline;
Matt Buckley50c44062022-01-17 20:48:10 +0000598
Matt Buckley1809d902022-08-05 06:51:43 +0000599 // Iterate over the displays that use hwc in the same order they are presented
Matt Buckley50c44062022-01-17 20:48:10 +0000600 for (DisplayId displayId : displayIds) {
601 if (mDisplayTimingData.count(displayId) == 0) {
602 continue;
603 }
604
605 auto& displayData = mDisplayTimingData.at(displayId);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700606
Matt Buckley0538cae2022-11-08 23:12:04 +0000607 displayTiming = displayData.calculateDisplayTimeline(mLastPresentFenceTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000608
Matt Buckley50c44062022-01-17 20:48:10 +0000609 // Update predicted present finish time with this display's present time
Matt Buckley0538cae2022-11-08 23:12:04 +0000610 estimatedHwcEndTime = displayTiming.hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000611
612 // Track how long we spent waiting for the fence, can be excluded from the timing estimate
Matt Buckley0538cae2022-11-08 23:12:04 +0000613 idleDuration += displayTiming.probablyWaitsForPresentFence
614 ? mLastPresentFenceTime - displayTiming.presentFenceWaitStartTime
Matt Buckley2fa85012022-08-30 22:38:45 +0000615 : 0ns;
Matt Buckley50c44062022-01-17 20:48:10 +0000616
617 // Track how long we spent waiting to present, can be excluded from the timing estimate
Matt Buckley0538cae2022-11-08 23:12:04 +0000618 idleDuration += displayTiming.hwcPresentDelayDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000619
620 // Estimate the reference frame's gpu timing
621 auto gpuTiming = displayData.estimateGpuTiming(previousValidGpuEndTime);
622 if (gpuTiming.has_value()) {
Xiang Wangaab31162024-03-12 19:48:08 -0700623 if (!firstGpuTimeline.has_value()) {
624 firstGpuTimeline = gpuTiming;
625 }
Matt Buckley50c44062022-01-17 20:48:10 +0000626 previousValidGpuEndTime = gpuTiming->startTime + gpuTiming->duration;
627
628 // Estimate the prediction frame's gpu end time from the reference frame
Matt Buckley0538cae2022-11-08 23:12:04 +0000629 estimatedGpuEndTime = std::max(displayTiming.hwcPresentStartTime,
Matt Buckley2fa85012022-08-30 22:38:45 +0000630 estimatedGpuEndTime.value_or(TimePoint{0ns})) +
Matt Buckley50c44062022-01-17 20:48:10 +0000631 gpuTiming->duration;
632 }
Matt Buckley50c44062022-01-17 20:48:10 +0000633 }
Matt Buckley50c44062022-01-17 20:48:10 +0000634
Matt Buckley0538cae2022-11-08 23:12:04 +0000635 TimePoint estimatedFlingerEndTime = mLastSfPresentEndTime;
Matt Buckley1809d902022-08-05 06:51:43 +0000636
Matt Buckley50c44062022-01-17 20:48:10 +0000637 // 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 +0000638 estimatedHwcEndTime -= idleDuration;
Matt Buckley1809d902022-08-05 06:51:43 +0000639 estimatedFlingerEndTime -= idleDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000640
641 // We finish the frame when both present and the gpu are done, so wait for the later of the two
642 // Also add the frame delay duration since the target did not move while we were delayed
Matt Buckley2fa85012022-08-30 22:38:45 +0000643 Duration totalDuration = mFrameDelayDuration +
Matt Buckley0538cae2022-11-08 23:12:04 +0000644 std::max(estimatedHwcEndTime, estimatedGpuEndTime.value_or(TimePoint{0ns})) -
Matt Buckley2fa85012022-08-30 22:38:45 +0000645 mCommitStartTimes[0];
Xiang Wangaab31162024-03-12 19:48:08 -0700646 Duration totalDurationWithoutGpu =
647 mFrameDelayDuration + estimatedHwcEndTime - mCommitStartTimes[0];
Matt Buckley50c44062022-01-17 20:48:10 +0000648
649 // We finish SurfaceFlinger when post-composition finishes, so add that in here
Matt Buckley2fa85012022-08-30 22:38:45 +0000650 Duration flingerDuration =
Matt Buckley1809d902022-08-05 06:51:43 +0000651 estimatedFlingerEndTime + mLastPostcompDuration - mCommitStartTimes[0];
Xiang Wangaab31162024-03-12 19:48:08 -0700652 Duration estimatedGpuDuration = firstGpuTimeline.has_value()
653 ? estimatedGpuEndTime.value_or(TimePoint{0ns}) - firstGpuTimeline->startTime
654 : Duration::fromNs(0);
Matt Buckley1809d902022-08-05 06:51:43 +0000655
656 // Combine the two timings into a single normalized one
Matt Buckley2fa85012022-08-30 22:38:45 +0000657 Duration combinedDuration = combineTimingEstimates(totalDuration, flingerDuration);
Xiang Wangaab31162024-03-12 19:48:08 -0700658 Duration cpuDuration = combineTimingEstimates(totalDurationWithoutGpu, flingerDuration);
Matt Buckley50c44062022-01-17 20:48:10 +0000659
Xiang Wangaab31162024-03-12 19:48:08 -0700660 WorkDuration duration{
661 .timeStampNanos = TimePoint::now().ns(),
662 .durationNanos = combinedDuration.ns(),
663 .workPeriodStartTimestampNanos = mCommitStartTimes[0].ns(),
Xiang Wangcb50bbd2024-04-18 16:57:54 -0700664 .cpuDurationNanos = supportsGpuReporting() ? cpuDuration.ns() : 0,
665 .gpuDurationNanos = supportsGpuReporting() ? estimatedGpuDuration.ns() : 0,
Xiang Wangaab31162024-03-12 19:48:08 -0700666 };
667 if (sTraceHintSessionData) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000668 SFTRACE_INT64("Idle duration", idleDuration.ns());
669 SFTRACE_INT64("Total duration", totalDuration.ns());
670 SFTRACE_INT64("Flinger duration", flingerDuration.ns());
Xiang Wangaab31162024-03-12 19:48:08 -0700671 }
672 return std::make_optional(duration);
Matt Buckley50c44062022-01-17 20:48:10 +0000673}
674
Matt Buckley2fa85012022-08-30 22:38:45 +0000675Duration PowerAdvisor::combineTimingEstimates(Duration totalDuration, Duration flingerDuration) {
676 Duration targetDuration{0ns};
Matt Buckley0538cae2022-11-08 23:12:04 +0000677 targetDuration = mTargetDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000678 if (!mTotalFrameTargetDuration.has_value()) return flingerDuration;
679
680 // Normalize total to the flinger target (vsync period) since that's how often we actually send
681 // hints
Matt Buckley2fa85012022-08-30 22:38:45 +0000682 Duration normalizedTotalDuration = Duration::fromNs((targetDuration.ns() * totalDuration.ns()) /
683 mTotalFrameTargetDuration->ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000684 return std::max(flingerDuration, normalizedTotalDuration);
685}
686
Matt Buckley50c44062022-01-17 20:48:10 +0000687PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimingData::calculateDisplayTimeline(
Matt Buckley2fa85012022-08-30 22:38:45 +0000688 TimePoint fenceTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000689 DisplayTimeline timeline;
Matt Buckley16dec1f2022-06-07 21:46:20 +0000690 // How long between calling hwc present and trying to wait on the fence
Matt Buckley2fa85012022-08-30 22:38:45 +0000691 const Duration fenceWaitStartDelay =
692 (skippedValidate ? kFenceWaitStartDelaySkippedValidate : kFenceWaitStartDelayValidated);
Matt Buckley50c44062022-01-17 20:48:10 +0000693
Matt Buckley16dec1f2022-06-07 21:46:20 +0000694 // Did our reference frame wait for an appropriate vsync before calling into hwc
695 const bool waitedOnHwcPresentTime = hwcPresentDelayedTime.has_value() &&
696 *hwcPresentDelayedTime > *hwcPresentStartTime &&
697 *hwcPresentDelayedTime < *hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000698
699 // Use validate start here if we skipped it because we did validate + present together
Matt Buckley16dec1f2022-06-07 21:46:20 +0000700 timeline.hwcPresentStartTime = skippedValidate ? *hwcValidateStartTime : *hwcPresentStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000701
702 // Use validate end here if we skipped it because we did validate + present together
Matt Buckley16dec1f2022-06-07 21:46:20 +0000703 timeline.hwcPresentEndTime = skippedValidate ? *hwcValidateEndTime : *hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000704
Matt Buckley16dec1f2022-06-07 21:46:20 +0000705 // How long hwc present was delayed waiting for the next appropriate vsync
706 timeline.hwcPresentDelayDuration =
Matt Buckley2fa85012022-08-30 22:38:45 +0000707 (waitedOnHwcPresentTime ? *hwcPresentDelayedTime - *hwcPresentStartTime : 0ns);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700708 // When we started waiting for the present fence after calling into hwc present
709 timeline.presentFenceWaitStartTime =
Matt Buckley16dec1f2022-06-07 21:46:20 +0000710 timeline.hwcPresentStartTime + timeline.hwcPresentDelayDuration + fenceWaitStartDelay;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700711 timeline.probablyWaitsForPresentFence = fenceTime > timeline.presentFenceWaitStartTime &&
Matt Buckley16dec1f2022-06-07 21:46:20 +0000712 fenceTime < timeline.hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000713
Matt Buckley16dec1f2022-06-07 21:46:20 +0000714 // How long we ran after we finished waiting for the fence but before hwc present finished
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700715 timeline.postPresentFenceHwcPresentDuration = timeline.hwcPresentEndTime -
716 (timeline.probablyWaitsForPresentFence ? fenceTime
717 : timeline.presentFenceWaitStartTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000718 return timeline;
719}
720
721std::optional<PowerAdvisor::GpuTimeline> PowerAdvisor::DisplayTimingData::estimateGpuTiming(
Matt Buckley2fa85012022-08-30 22:38:45 +0000722 std::optional<TimePoint> previousEndTime) {
Xiang Wangaab31162024-03-12 19:48:08 -0700723 if (!(requiresRenderEngine && lastValidGpuStartTime.has_value() && gpuEndFenceTime)) {
Matt Buckley50c44062022-01-17 20:48:10 +0000724 return std::nullopt;
725 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000726 const TimePoint latestGpuStartTime =
727 std::max(previousEndTime.value_or(TimePoint{0ns}), *gpuStartTime);
728 const nsecs_t gpuEndFenceSignal = gpuEndFenceTime->getSignalTime();
729 Duration gpuDuration{0ns};
730 if (gpuEndFenceSignal != Fence::SIGNAL_TIME_INVALID &&
731 gpuEndFenceSignal != Fence::SIGNAL_TIME_PENDING) {
732 const TimePoint latestGpuEndTime = TimePoint::fromNs(gpuEndFenceSignal);
733
Matt Buckley50c44062022-01-17 20:48:10 +0000734 // If we know how long the most recent gpu duration was, use that
735 gpuDuration = latestGpuEndTime - latestGpuStartTime;
736 } else if (lastValidGpuEndTime.has_value()) {
737 // If we don't have the fence data, use the most recent information we do have
738 gpuDuration = *lastValidGpuEndTime - *lastValidGpuStartTime;
Matt Buckley2fa85012022-08-30 22:38:45 +0000739 if (gpuEndFenceSignal == Fence::SIGNAL_TIME_PENDING) {
Matt Buckley50c44062022-01-17 20:48:10 +0000740 // If pending but went over the previous duration, use current time as the end
Matt Buckley2fa85012022-08-30 22:38:45 +0000741 gpuDuration = std::max(gpuDuration, Duration{TimePoint::now() - latestGpuStartTime});
Matt Buckley50c44062022-01-17 20:48:10 +0000742 }
743 }
744 return GpuTimeline{.duration = gpuDuration, .startTime = latestGpuStartTime};
745}
746
Matt Buckley0538cae2022-11-08 23:12:04 +0000747const bool PowerAdvisor::sTraceHintSessionData =
Xiang Wang56dc1042024-03-22 03:58:46 +0000748 base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
Matt Buckleyef51fba2021-10-12 19:30:12 +0000749
Matt Buckleyac15a1b2023-02-28 06:51:28 +0000750const Duration PowerAdvisor::sTargetSafetyMargin = std::chrono::microseconds(
751 base::GetIntProperty<int64_t>("debug.sf.hint_margin_us",
752 ticks<std::micro>(PowerAdvisor::kDefaultTargetSafetyMargin)));
753
Matt Buckley676e4392023-05-25 22:09:26 +0000754const bool PowerAdvisor::sUseReportActualDuration =
755 base::GetBoolProperty(std::string("debug.adpf.use_report_actual_duration"), true);
756
Matt Buckley0538cae2022-11-08 23:12:04 +0000757power::PowerHalController& PowerAdvisor::getPowerHal() {
758 static std::once_flag halFlag;
759 std::call_once(halFlag, [this] { mPowerHal->init(); });
760 return *mPowerHal;
Michael Wright1509a232018-06-21 02:50:34 +0100761}
762
763} // namespace impl
764} // namespace Hwc2
765} // namespace android