blob: f05223cce05a736115d4aa17ed38ac03c4715aa3 [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 <android/hardware/power/1.3/IPower.h>
Matt Buckley06f299a2021-09-24 19:43:51 +000035#include <android/hardware/power/IPowerHintSession.h>
36#include <android/hardware/power/WorkDuration.h>
37
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
52namespace V1_0 = android::hardware::power::V1_0;
Dan Stoza030fbc12020-02-19 15:32:01 -080053namespace V1_3 = android::hardware::power::V1_3;
Michael Wright1509a232018-06-21 02:50:34 +010054using V1_3::PowerHint;
55
Dan Stoza030fbc12020-02-19 15:32:01 -080056using android::hardware::power::Boost;
57using android::hardware::power::IPower;
Matt Buckley06f299a2021-09-24 19:43:51 +000058using android::hardware::power::IPowerHintSession;
Dan Stoza030fbc12020-02-19 15:32:01 -080059using android::hardware::power::Mode;
Matt Buckley15ecd1c2022-11-01 21:57:16 +000060using android::hardware::power::SessionHint;
Matt Buckley06f299a2021-09-24 19:43:51 +000061using android::hardware::power::WorkDuration;
62
Michael Wright1509a232018-06-21 02:50:34 +010063PowerAdvisor::~PowerAdvisor() = default;
64
Dan Stoza030fbc12020-02-19 15:32:01 -080065namespace {
Alec Mouri29382ad2022-05-11 18:38:38 +000066std::chrono::milliseconds getUpdateTimeout() {
Dan Stoza030fbc12020-02-19 15:32:01 -080067 // Default to a timeout of 80ms if nothing else is specified
Alec Mouri29382ad2022-05-11 18:38:38 +000068 static std::chrono::milliseconds timeout =
69 std::chrono::milliseconds(sysprop::display_update_imminent_timeout_ms(80));
Dan Stoza030fbc12020-02-19 15:32:01 -080070 return timeout;
71}
72
Ady Abrahamabce1652022-02-24 10:51:19 -080073void traceExpensiveRendering(bool enabled) {
74 if (enabled) {
75 ATRACE_ASYNC_BEGIN("ExpensiveRendering", 0);
76 } else {
77 ATRACE_ASYNC_END("ExpensiveRendering", 0);
78 }
79}
80
Dan Stoza030fbc12020-02-19 15:32:01 -080081} // namespace
82
Alec Mouric059dcf2022-05-05 23:40:07 +000083PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger) : mFlinger(flinger) {
Alec Mouri29382ad2022-05-11 18:38:38 +000084 if (getUpdateTimeout() > 0ms) {
85 mScreenUpdateTimer.emplace("UpdateImminentTimer", getUpdateTimeout(),
Alec Mouric059dcf2022-05-05 23:40:07 +000086 /* resetCallback */ nullptr,
87 /* timeoutCallback */
88 [this] {
Alec Mouri29382ad2022-05-11 18:38:38 +000089 while (true) {
90 auto timeSinceLastUpdate = std::chrono::nanoseconds(
91 systemTime() - mLastScreenUpdatedTime.load());
92 if (timeSinceLastUpdate >= getUpdateTimeout()) {
93 break;
94 }
Alec Mouric059dcf2022-05-05 23:40:07 +000095 // We may try to disable expensive rendering and allow
96 // for sending DISPLAY_UPDATE_IMMINENT hints too early if
97 // we idled very shortly after updating the screen, so
98 // make sure we wait enough time.
Alec Mouri29382ad2022-05-11 18:38:38 +000099 std::this_thread::sleep_for(getUpdateTimeout() -
100 timeSinceLastUpdate);
Alec Mouric059dcf2022-05-05 23:40:07 +0000101 }
102 mSendUpdateImminent.store(true);
103 mFlinger.disableExpensiveRendering();
104 });
105 }
106}
Alec Mouridea1ac52021-06-23 18:12:18 -0700107
108void PowerAdvisor::init() {
109 // Defer starting the screen update timer until SurfaceFlinger finishes construction.
Alec Mouric059dcf2022-05-05 23:40:07 +0000110 if (mScreenUpdateTimer) {
111 mScreenUpdateTimer->start();
Dan Stoza030fbc12020-02-19 15:32:01 -0800112 }
113}
Michael Wright1509a232018-06-21 02:50:34 +0100114
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700115void PowerAdvisor::onBootFinished() {
116 mBootFinished.store(true);
117}
118
Peiyong Lin74ca2f42019-01-14 19:36:57 -0800119void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
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) {
Dan Stoza20950002020-06-18 14:56:58 -0700128 std::lock_guard lock(mPowerHalMutex);
Dan Stoza030fbc12020-02-19 15:32:01 -0800129 HalWrapper* const halWrapper = getPowerHal();
130 if (halWrapper == nullptr) {
Peiyong Lin81934972018-07-02 11:00:54 -0700131 return;
132 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800133
134 if (!halWrapper->setExpensiveRendering(expectsExpensiveRendering)) {
135 // The HAL has become unavailable; attempt to reconnect later
Michael Wright1509a232018-06-21 02:50:34 +0100136 mReconnectPowerHal = true;
137 return;
138 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800139
Michael Wright1509a232018-06-21 02:50:34 +0100140 mNotifiedExpensiveRendering = expectsExpensiveRendering;
141 }
142}
143
Matt Buckley15ecd1c2022-11-01 21:57:16 +0000144void PowerAdvisor::notifyDisplayUpdateImminentAndCpuReset() {
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700145 // Only start sending this notification once the system has booted so we don't introduce an
146 // early-boot dependency on Power HAL
147 if (!mBootFinished.load()) {
148 return;
149 }
150
Alec Mouric059dcf2022-05-05 23:40:07 +0000151 if (mSendUpdateImminent.exchange(false)) {
Dan Stoza20950002020-06-18 14:56:58 -0700152 std::lock_guard lock(mPowerHalMutex);
Dan Stoza030fbc12020-02-19 15:32:01 -0800153 HalWrapper* const halWrapper = getPowerHal();
154 if (halWrapper == nullptr) {
155 return;
156 }
157
Matt Buckley15ecd1c2022-11-01 21:57:16 +0000158 if (!halWrapper->notifyDisplayUpdateImminentAndCpuReset()) {
Dan Stoza030fbc12020-02-19 15:32:01 -0800159 // The HAL has become unavailable; attempt to reconnect later
160 mReconnectPowerHal = true;
161 return;
162 }
Alec Mouric059dcf2022-05-05 23:40:07 +0000163
164 if (mScreenUpdateTimer) {
165 mScreenUpdateTimer->reset();
166 } else {
167 // If we don't have a screen update timer, then we don't throttle power hal calls so
168 // flip this bit back to allow for calling into power hal again.
169 mSendUpdateImminent.store(true);
170 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800171 }
172
Alec Mouric059dcf2022-05-05 23:40:07 +0000173 if (mScreenUpdateTimer) {
174 mLastScreenUpdatedTime.store(systemTime());
Dan Stoza030fbc12020-02-19 15:32:01 -0800175 }
176}
177
Matt Buckley06f299a2021-09-24 19:43:51 +0000178// checks both if it supports and if it's enabled
179bool PowerAdvisor::usePowerHintSession() {
180 // uses cached value since the underlying support and flag are unlikely to change at runtime
Matt Buckley06f299a2021-09-24 19:43:51 +0000181 return mPowerHintEnabled.value_or(false) && supportsPowerHintSession();
182}
183
184bool PowerAdvisor::supportsPowerHintSession() {
185 // cache to avoid needing lock every time
186 if (!mSupportsPowerHint.has_value()) {
187 std::lock_guard lock(mPowerHalMutex);
188 HalWrapper* const halWrapper = getPowerHal();
Shao-Chuan Lee65a2c192022-07-27 09:53:41 +0900189 mSupportsPowerHint = halWrapper && halWrapper->supportsPowerHintSession();
Matt Buckley06f299a2021-09-24 19:43:51 +0000190 }
191 return *mSupportsPowerHint;
192}
193
194bool PowerAdvisor::isPowerHintSessionRunning() {
195 return mPowerHintSessionRunning;
196}
197
Matt Buckley2fa85012022-08-30 22:38:45 +0000198void PowerAdvisor::setTargetWorkDuration(Duration targetDuration) {
Matt Buckleyef51fba2021-10-12 19:30:12 +0000199 if (!usePowerHintSession()) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000200 ALOGV("Power hint session target duration cannot be set, skipping");
201 return;
202 }
203 {
204 std::lock_guard lock(mPowerHalMutex);
205 HalWrapper* const halWrapper = getPowerHal();
206 if (halWrapper != nullptr) {
Matt Buckley50c44062022-01-17 20:48:10 +0000207 halWrapper->setTargetWorkDuration(targetDuration);
Matt Buckley06f299a2021-09-24 19:43:51 +0000208 }
209 }
210}
211
Matt Buckley50c44062022-01-17 20:48:10 +0000212void PowerAdvisor::sendActualWorkDuration() {
Matt Buckley06f299a2021-09-24 19:43:51 +0000213 if (!mBootFinished || !usePowerHintSession()) {
214 ALOGV("Actual work duration power hint cannot be sent, skipping");
215 return;
216 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000217 const std::optional<Duration> actualDuration = estimateWorkDuration(false);
Matt Buckley50c44062022-01-17 20:48:10 +0000218 if (actualDuration.has_value()) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000219 std::lock_guard lock(mPowerHalMutex);
220 HalWrapper* const halWrapper = getPowerHal();
221 if (halWrapper != nullptr) {
Matt Buckley2fa85012022-08-30 22:38:45 +0000222 halWrapper->sendActualWorkDuration(*actualDuration + kTargetSafetyMargin,
223 TimePoint::now());
Matt Buckley06f299a2021-09-24 19:43:51 +0000224 }
225 }
226}
227
Matt Buckley50c44062022-01-17 20:48:10 +0000228void PowerAdvisor::sendPredictedWorkDuration() {
229 if (!mBootFinished || !usePowerHintSession()) {
230 ALOGV("Actual work duration power hint cannot be sent, skipping");
231 return;
232 }
233
Matt Buckley2fa85012022-08-30 22:38:45 +0000234 const std::optional<Duration> predictedDuration = estimateWorkDuration(true);
Matt Buckley50c44062022-01-17 20:48:10 +0000235
236 if (predictedDuration.has_value()) {
237 std::lock_guard lock(mPowerHalMutex);
238 HalWrapper* const halWrapper = getPowerHal();
239 if (halWrapper != nullptr) {
Matt Buckley2fa85012022-08-30 22:38:45 +0000240 halWrapper->sendActualWorkDuration(*predictedDuration + kTargetSafetyMargin,
241 TimePoint::now());
Matt Buckley50c44062022-01-17 20:48:10 +0000242 }
243 }
244}
245
Matt Buckley06f299a2021-09-24 19:43:51 +0000246void PowerAdvisor::enablePowerHint(bool enabled) {
247 mPowerHintEnabled = enabled;
248}
249
Matt Buckleyef51fba2021-10-12 19:30:12 +0000250bool PowerAdvisor::startPowerHintSession(const std::vector<int32_t>& threadIds) {
251 if (!usePowerHintSession()) {
252 ALOGI("Power hint session cannot be started, skipping");
253 }
254 {
255 std::lock_guard lock(mPowerHalMutex);
256 HalWrapper* halWrapper = getPowerHal();
257 if (halWrapper != nullptr && usePowerHintSession()) {
258 halWrapper->setPowerHintSessionThreadIds(threadIds);
259 mPowerHintSessionRunning = halWrapper->startPowerHintSession();
260 }
261 }
262 return mPowerHintSessionRunning;
263}
264
Matt Buckley50c44062022-01-17 20:48:10 +0000265void PowerAdvisor::setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime) {
266 DisplayTimingData& displayData = mDisplayTimingData[displayId];
267 if (displayData.gpuEndFenceTime) {
268 nsecs_t signalTime = displayData.gpuEndFenceTime->getSignalTime();
269 if (signalTime != Fence::SIGNAL_TIME_INVALID && signalTime != Fence::SIGNAL_TIME_PENDING) {
270 for (auto&& [_, otherDisplayData] : mDisplayTimingData) {
271 // If the previous display started before us but ended after we should have
272 // started, then it likely delayed our start time and we must compensate for that.
273 // Displays finishing earlier should have already made their way through this call
274 // and swapped their timing into "lastValid" from "latest", so we check that here.
275 if (!otherDisplayData.lastValidGpuStartTime.has_value()) continue;
276 if ((*otherDisplayData.lastValidGpuStartTime < *displayData.gpuStartTime) &&
277 (*otherDisplayData.lastValidGpuEndTime > *displayData.gpuStartTime)) {
278 displayData.lastValidGpuStartTime = *otherDisplayData.lastValidGpuEndTime;
279 break;
280 }
281 }
282 displayData.lastValidGpuStartTime = displayData.gpuStartTime;
Matt Buckley2fa85012022-08-30 22:38:45 +0000283 displayData.lastValidGpuEndTime = TimePoint::fromNs(signalTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000284 }
285 }
286 displayData.gpuEndFenceTime = std::move(fenceTime);
Matt Buckley2fa85012022-08-30 22:38:45 +0000287 displayData.gpuStartTime = TimePoint::now();
Matt Buckley50c44062022-01-17 20:48:10 +0000288}
289
Matt Buckley2fa85012022-08-30 22:38:45 +0000290void PowerAdvisor::setHwcValidateTiming(DisplayId displayId, TimePoint validateStartTime,
291 TimePoint validateEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000292 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000293 displayData.hwcValidateStartTime = validateStartTime;
294 displayData.hwcValidateEndTime = validateEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000295}
296
Matt Buckley2fa85012022-08-30 22:38:45 +0000297void PowerAdvisor::setHwcPresentTiming(DisplayId displayId, TimePoint presentStartTime,
298 TimePoint presentEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000299 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000300 displayData.hwcPresentStartTime = presentStartTime;
301 displayData.hwcPresentEndTime = presentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000302}
303
304void PowerAdvisor::setSkippedValidate(DisplayId displayId, bool skipped) {
305 mDisplayTimingData[displayId].skippedValidate = skipped;
306}
307
308void PowerAdvisor::setRequiresClientComposition(DisplayId displayId,
309 bool requiresClientComposition) {
310 mDisplayTimingData[displayId].usedClientComposition = requiresClientComposition;
311}
312
Matt Buckley2fa85012022-08-30 22:38:45 +0000313void PowerAdvisor::setExpectedPresentTime(TimePoint expectedPresentTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000314 mExpectedPresentTimes.append(expectedPresentTime);
315}
316
Matt Buckley2fa85012022-08-30 22:38:45 +0000317void PowerAdvisor::setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) {
Matt Buckley1809d902022-08-05 06:51:43 +0000318 mLastSfPresentEndTime = presentEndTime;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700319 mLastPresentFenceTime = presentFenceTime;
320}
321
Matt Buckley2fa85012022-08-30 22:38:45 +0000322void PowerAdvisor::setFrameDelay(Duration frameDelayDuration) {
Matt Buckley50c44062022-01-17 20:48:10 +0000323 mFrameDelayDuration = frameDelayDuration;
324}
325
Matt Buckley2fa85012022-08-30 22:38:45 +0000326void PowerAdvisor::setHwcPresentDelayedTime(DisplayId displayId, TimePoint earliestFrameStartTime) {
327 mDisplayTimingData[displayId].hwcPresentDelayedTime = earliestFrameStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000328}
329
Matt Buckley2fa85012022-08-30 22:38:45 +0000330void PowerAdvisor::setCommitStart(TimePoint commitStartTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000331 mCommitStartTimes.append(commitStartTime);
332}
333
Matt Buckley2fa85012022-08-30 22:38:45 +0000334void PowerAdvisor::setCompositeEnd(TimePoint compositeEndTime) {
335 mLastPostcompDuration = compositeEndTime - mLastSfPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000336}
337
338void PowerAdvisor::setDisplays(std::vector<DisplayId>& displayIds) {
339 mDisplayIds = displayIds;
340}
341
Matt Buckley2fa85012022-08-30 22:38:45 +0000342void PowerAdvisor::setTotalFrameTargetWorkDuration(Duration targetDuration) {
Matt Buckley50c44062022-01-17 20:48:10 +0000343 mTotalFrameTargetDuration = targetDuration;
344}
345
346std::vector<DisplayId> PowerAdvisor::getOrderedDisplayIds(
Matt Buckley2fa85012022-08-30 22:38:45 +0000347 std::optional<TimePoint> DisplayTimingData::*sortBy) {
Matt Buckley50c44062022-01-17 20:48:10 +0000348 std::vector<DisplayId> sortedDisplays;
349 std::copy_if(mDisplayIds.begin(), mDisplayIds.end(), std::back_inserter(sortedDisplays),
350 [&](DisplayId id) {
351 return mDisplayTimingData.count(id) &&
352 (mDisplayTimingData[id].*sortBy).has_value();
353 });
354 std::sort(sortedDisplays.begin(), sortedDisplays.end(), [&](DisplayId idA, DisplayId idB) {
355 return *(mDisplayTimingData[idA].*sortBy) < *(mDisplayTimingData[idB].*sortBy);
356 });
357 return sortedDisplays;
358}
359
Matt Buckley2fa85012022-08-30 22:38:45 +0000360std::optional<Duration> PowerAdvisor::estimateWorkDuration(bool earlyHint) {
Matt Buckley50c44062022-01-17 20:48:10 +0000361 if (earlyHint && (!mExpectedPresentTimes.isFull() || !mCommitStartTimes.isFull())) {
362 return std::nullopt;
363 }
364
365 // Tracks when we finish presenting to hwc
Matt Buckley2fa85012022-08-30 22:38:45 +0000366 TimePoint estimatedEndTime = mCommitStartTimes[0];
Matt Buckley50c44062022-01-17 20:48:10 +0000367
368 // How long we spent this frame not doing anything, waiting for fences or vsync
Matt Buckley2fa85012022-08-30 22:38:45 +0000369 Duration idleDuration = 0ns;
Matt Buckley50c44062022-01-17 20:48:10 +0000370
371 // Most recent previous gpu end time in the current frame, probably from a prior display, used
372 // 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 +0000373 std::optional<TimePoint> previousValidGpuEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000374
375 // The currently estimated gpu end time for the frame,
376 // used to accumulate gpu time as we iterate over the active displays
Matt Buckley2fa85012022-08-30 22:38:45 +0000377 std::optional<TimePoint> estimatedGpuEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000378
379 // If we're predicting at the start of the frame, we use last frame as our reference point
380 // If we're predicting at the end of the frame, we use the current frame as a reference point
Matt Buckley2fa85012022-08-30 22:38:45 +0000381 TimePoint referenceFrameStartTime = (earlyHint ? mCommitStartTimes[-1] : mCommitStartTimes[0]);
Matt Buckley50c44062022-01-17 20:48:10 +0000382
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700383 // When the prior frame should be presenting to the display
384 // If we're predicting at the start of the frame, we use last frame's expected present time
385 // If we're predicting at the end of the frame, the present fence time is already known
Matt Buckley2fa85012022-08-30 22:38:45 +0000386 TimePoint lastFramePresentTime =
387 (earlyHint ? mExpectedPresentTimes[-1] : mLastPresentFenceTime);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700388
Matt Buckley50c44062022-01-17 20:48:10 +0000389 // The timing info for the previously calculated display, if there was one
390 std::optional<DisplayTimeline> previousDisplayReferenceTiming;
391 std::vector<DisplayId>&& displayIds =
Matt Buckley16dec1f2022-06-07 21:46:20 +0000392 getOrderedDisplayIds(&DisplayTimingData::hwcPresentStartTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000393 DisplayTimeline referenceTiming, estimatedTiming;
394
Matt Buckley1809d902022-08-05 06:51:43 +0000395 // Iterate over the displays that use hwc in the same order they are presented
Matt Buckley50c44062022-01-17 20:48:10 +0000396 for (DisplayId displayId : displayIds) {
397 if (mDisplayTimingData.count(displayId) == 0) {
398 continue;
399 }
400
401 auto& displayData = mDisplayTimingData.at(displayId);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700402
403 // mLastPresentFenceTime should always be the time of the reference frame, since it will be
404 // the previous frame's present fence if called at the start, and current frame's if called
405 // at the end
406 referenceTiming = displayData.calculateDisplayTimeline(mLastPresentFenceTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000407
Matt Buckley16dec1f2022-06-07 21:46:20 +0000408 // If this is the first display, include the duration before hwc present starts
Matt Buckley50c44062022-01-17 20:48:10 +0000409 if (!previousDisplayReferenceTiming.has_value()) {
Matt Buckley16dec1f2022-06-07 21:46:20 +0000410 estimatedEndTime += referenceTiming.hwcPresentStartTime - referenceFrameStartTime;
411 } else { // Otherwise add the time since last display's hwc present finished
412 estimatedEndTime += referenceTiming.hwcPresentStartTime -
413 previousDisplayReferenceTiming->hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000414 }
415
Matt Buckley50689e82022-06-21 13:23:27 -0700416 // Late hint can re-use reference timing here since it's estimating its own reference frame
417 estimatedTiming = earlyHint
418 ? referenceTiming.estimateTimelineFromReference(lastFramePresentTime,
419 estimatedEndTime)
420 : referenceTiming;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700421
Matt Buckley50c44062022-01-17 20:48:10 +0000422 // Update predicted present finish time with this display's present time
Matt Buckley16dec1f2022-06-07 21:46:20 +0000423 estimatedEndTime = estimatedTiming.hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000424
425 // Track how long we spent waiting for the fence, can be excluded from the timing estimate
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700426 idleDuration += estimatedTiming.probablyWaitsForPresentFence
427 ? lastFramePresentTime - estimatedTiming.presentFenceWaitStartTime
Matt Buckley2fa85012022-08-30 22:38:45 +0000428 : 0ns;
Matt Buckley50c44062022-01-17 20:48:10 +0000429
430 // Track how long we spent waiting to present, can be excluded from the timing estimate
Matt Buckley2fa85012022-08-30 22:38:45 +0000431 idleDuration += earlyHint ? 0ns : referenceTiming.hwcPresentDelayDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000432
433 // Estimate the reference frame's gpu timing
434 auto gpuTiming = displayData.estimateGpuTiming(previousValidGpuEndTime);
435 if (gpuTiming.has_value()) {
436 previousValidGpuEndTime = gpuTiming->startTime + gpuTiming->duration;
437
438 // Estimate the prediction frame's gpu end time from the reference frame
Matt Buckley2fa85012022-08-30 22:38:45 +0000439 estimatedGpuEndTime = std::max(estimatedTiming.hwcPresentStartTime,
440 estimatedGpuEndTime.value_or(TimePoint{0ns})) +
Matt Buckley50c44062022-01-17 20:48:10 +0000441 gpuTiming->duration;
442 }
443 previousDisplayReferenceTiming = referenceTiming;
444 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000445 ATRACE_INT64("Idle duration", idleDuration.ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000446
Matt Buckley2fa85012022-08-30 22:38:45 +0000447 TimePoint estimatedFlingerEndTime = earlyHint ? estimatedEndTime : mLastSfPresentEndTime;
Matt Buckley1809d902022-08-05 06:51:43 +0000448
Matt Buckley50c44062022-01-17 20:48:10 +0000449 // Don't count time spent idly waiting in the estimate as we could do more work in that time
450 estimatedEndTime -= idleDuration;
Matt Buckley1809d902022-08-05 06:51:43 +0000451 estimatedFlingerEndTime -= idleDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000452
453 // We finish the frame when both present and the gpu are done, so wait for the later of the two
454 // Also add the frame delay duration since the target did not move while we were delayed
Matt Buckley2fa85012022-08-30 22:38:45 +0000455 Duration totalDuration = mFrameDelayDuration +
456 std::max(estimatedEndTime, estimatedGpuEndTime.value_or(TimePoint{0ns})) -
457 mCommitStartTimes[0];
Matt Buckley50c44062022-01-17 20:48:10 +0000458
459 // We finish SurfaceFlinger when post-composition finishes, so add that in here
Matt Buckley2fa85012022-08-30 22:38:45 +0000460 Duration flingerDuration =
Matt Buckley1809d902022-08-05 06:51:43 +0000461 estimatedFlingerEndTime + mLastPostcompDuration - mCommitStartTimes[0];
462
463 // Combine the two timings into a single normalized one
Matt Buckley2fa85012022-08-30 22:38:45 +0000464 Duration combinedDuration = combineTimingEstimates(totalDuration, flingerDuration);
Matt Buckley50c44062022-01-17 20:48:10 +0000465
466 return std::make_optional(combinedDuration);
467}
468
Matt Buckley2fa85012022-08-30 22:38:45 +0000469Duration PowerAdvisor::combineTimingEstimates(Duration totalDuration, Duration flingerDuration) {
470 Duration targetDuration{0ns};
Matt Buckley50c44062022-01-17 20:48:10 +0000471 {
472 std::lock_guard lock(mPowerHalMutex);
473 targetDuration = *getPowerHal()->getTargetWorkDuration();
474 }
475 if (!mTotalFrameTargetDuration.has_value()) return flingerDuration;
476
477 // Normalize total to the flinger target (vsync period) since that's how often we actually send
478 // hints
Matt Buckley2fa85012022-08-30 22:38:45 +0000479 Duration normalizedTotalDuration = Duration::fromNs((targetDuration.ns() * totalDuration.ns()) /
480 mTotalFrameTargetDuration->ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000481 return std::max(flingerDuration, normalizedTotalDuration);
482}
483
484PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimeline::estimateTimelineFromReference(
Matt Buckley2fa85012022-08-30 22:38:45 +0000485 TimePoint fenceTime, TimePoint displayStartTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000486 DisplayTimeline estimated;
Matt Buckley16dec1f2022-06-07 21:46:20 +0000487 estimated.hwcPresentStartTime = displayStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000488
489 // We don't predict waiting for vsync alignment yet
Matt Buckley2fa85012022-08-30 22:38:45 +0000490 estimated.hwcPresentDelayDuration = 0ns;
Matt Buckley50c44062022-01-17 20:48:10 +0000491
Matt Buckley50c44062022-01-17 20:48:10 +0000492 // How long we expect to run before we start waiting for the fence
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700493 // For now just re-use last frame's post-present duration and assume it will not change much
494 // Excludes time spent waiting for vsync since that's not going to be consistent
495 estimated.presentFenceWaitStartTime = estimated.hwcPresentStartTime +
496 (presentFenceWaitStartTime - (hwcPresentStartTime + hwcPresentDelayDuration));
497 estimated.probablyWaitsForPresentFence = fenceTime > estimated.presentFenceWaitStartTime;
498 estimated.hwcPresentEndTime = postPresentFenceHwcPresentDuration +
499 (estimated.probablyWaitsForPresentFence ? fenceTime
500 : estimated.presentFenceWaitStartTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000501 return estimated;
502}
503
504PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimingData::calculateDisplayTimeline(
Matt Buckley2fa85012022-08-30 22:38:45 +0000505 TimePoint fenceTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000506 DisplayTimeline timeline;
Matt Buckley16dec1f2022-06-07 21:46:20 +0000507 // How long between calling hwc present and trying to wait on the fence
Matt Buckley2fa85012022-08-30 22:38:45 +0000508 const Duration fenceWaitStartDelay =
509 (skippedValidate ? kFenceWaitStartDelaySkippedValidate : kFenceWaitStartDelayValidated);
Matt Buckley50c44062022-01-17 20:48:10 +0000510
Matt Buckley16dec1f2022-06-07 21:46:20 +0000511 // Did our reference frame wait for an appropriate vsync before calling into hwc
512 const bool waitedOnHwcPresentTime = hwcPresentDelayedTime.has_value() &&
513 *hwcPresentDelayedTime > *hwcPresentStartTime &&
514 *hwcPresentDelayedTime < *hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000515
516 // Use validate start here if we skipped it because we did validate + present together
Matt Buckley16dec1f2022-06-07 21:46:20 +0000517 timeline.hwcPresentStartTime = skippedValidate ? *hwcValidateStartTime : *hwcPresentStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000518
519 // Use validate end here if we skipped it because we did validate + present together
Matt Buckley16dec1f2022-06-07 21:46:20 +0000520 timeline.hwcPresentEndTime = skippedValidate ? *hwcValidateEndTime : *hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000521
Matt Buckley16dec1f2022-06-07 21:46:20 +0000522 // How long hwc present was delayed waiting for the next appropriate vsync
523 timeline.hwcPresentDelayDuration =
Matt Buckley2fa85012022-08-30 22:38:45 +0000524 (waitedOnHwcPresentTime ? *hwcPresentDelayedTime - *hwcPresentStartTime : 0ns);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700525 // When we started waiting for the present fence after calling into hwc present
526 timeline.presentFenceWaitStartTime =
Matt Buckley16dec1f2022-06-07 21:46:20 +0000527 timeline.hwcPresentStartTime + timeline.hwcPresentDelayDuration + fenceWaitStartDelay;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700528 timeline.probablyWaitsForPresentFence = fenceTime > timeline.presentFenceWaitStartTime &&
Matt Buckley16dec1f2022-06-07 21:46:20 +0000529 fenceTime < timeline.hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000530
Matt Buckley16dec1f2022-06-07 21:46:20 +0000531 // How long we ran after we finished waiting for the fence but before hwc present finished
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700532 timeline.postPresentFenceHwcPresentDuration = timeline.hwcPresentEndTime -
533 (timeline.probablyWaitsForPresentFence ? fenceTime
534 : timeline.presentFenceWaitStartTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000535 return timeline;
536}
537
538std::optional<PowerAdvisor::GpuTimeline> PowerAdvisor::DisplayTimingData::estimateGpuTiming(
Matt Buckley2fa85012022-08-30 22:38:45 +0000539 std::optional<TimePoint> previousEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000540 if (!(usedClientComposition && lastValidGpuStartTime.has_value() && gpuEndFenceTime)) {
541 return std::nullopt;
542 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000543 const TimePoint latestGpuStartTime =
544 std::max(previousEndTime.value_or(TimePoint{0ns}), *gpuStartTime);
545 const nsecs_t gpuEndFenceSignal = gpuEndFenceTime->getSignalTime();
546 Duration gpuDuration{0ns};
547 if (gpuEndFenceSignal != Fence::SIGNAL_TIME_INVALID &&
548 gpuEndFenceSignal != Fence::SIGNAL_TIME_PENDING) {
549 const TimePoint latestGpuEndTime = TimePoint::fromNs(gpuEndFenceSignal);
550
Matt Buckley50c44062022-01-17 20:48:10 +0000551 // If we know how long the most recent gpu duration was, use that
552 gpuDuration = latestGpuEndTime - latestGpuStartTime;
553 } else if (lastValidGpuEndTime.has_value()) {
554 // If we don't have the fence data, use the most recent information we do have
555 gpuDuration = *lastValidGpuEndTime - *lastValidGpuStartTime;
Matt Buckley2fa85012022-08-30 22:38:45 +0000556 if (gpuEndFenceSignal == Fence::SIGNAL_TIME_PENDING) {
Matt Buckley50c44062022-01-17 20:48:10 +0000557 // If pending but went over the previous duration, use current time as the end
Matt Buckley2fa85012022-08-30 22:38:45 +0000558 gpuDuration = std::max(gpuDuration, Duration{TimePoint::now() - latestGpuStartTime});
Matt Buckley50c44062022-01-17 20:48:10 +0000559 }
560 }
561 return GpuTimeline{.duration = gpuDuration, .startTime = latestGpuStartTime};
562}
563
Dan Stoza030fbc12020-02-19 15:32:01 -0800564class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
565public:
566 HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
567
568 ~HidlPowerHalWrapper() override = default;
569
570 static std::unique_ptr<HalWrapper> connect() {
571 // Power HAL 1.3 is not guaranteed to be available, thus we need to query
572 // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
Dan Stoza030fbc12020-02-19 15:32:01 -0800573 sp<V1_3::IPower> powerHal = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800574 sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
575 if (powerHal_1_0 != nullptr) {
576 // Try to cast to Power HAL 1.3
577 powerHal = V1_3::IPower::castFrom(powerHal_1_0);
578 if (powerHal == nullptr) {
579 ALOGW("No Power HAL 1.3 service in system, disabling PowerAdvisor");
580 } else {
581 ALOGI("Loaded Power HAL 1.3 service");
Dan Stoza030fbc12020-02-19 15:32:01 -0800582 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800583 } else {
584 ALOGW("No Power HAL found, disabling PowerAdvisor");
Dan Stoza030fbc12020-02-19 15:32:01 -0800585 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800586
Dan Stoza030fbc12020-02-19 15:32:01 -0800587 if (powerHal == nullptr) {
588 return nullptr;
589 }
590
591 return std::make_unique<HidlPowerHalWrapper>(std::move(powerHal));
592 }
593
594 bool setExpensiveRendering(bool enabled) override {
595 ALOGV("HIDL setExpensiveRendering %s", enabled ? "T" : "F");
596 auto ret = mPowerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING, enabled);
Ady Abrahamabce1652022-02-24 10:51:19 -0800597 if (ret.isOk()) {
598 traceExpensiveRendering(enabled);
599 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800600 return ret.isOk();
601 }
602
Matt Buckley15ecd1c2022-11-01 21:57:16 +0000603 bool notifyDisplayUpdateImminentAndCpuReset() override {
Dan Stoza030fbc12020-02-19 15:32:01 -0800604 // Power HAL 1.x doesn't have a notification for this
605 ALOGV("HIDL notifyUpdateImminent received but can't send");
606 return true;
607 }
608
Matt Buckley06f299a2021-09-24 19:43:51 +0000609 bool supportsPowerHintSession() override { return false; }
610
611 bool isPowerHintSessionRunning() override { return false; }
612
613 void restartPowerHintSession() override {}
614
615 void setPowerHintSessionThreadIds(const std::vector<int32_t>&) override {}
616
617 bool startPowerHintSession() override { return false; }
618
Matt Buckley2fa85012022-08-30 22:38:45 +0000619 void setTargetWorkDuration(Duration) override {}
Matt Buckley06f299a2021-09-24 19:43:51 +0000620
Matt Buckley2fa85012022-08-30 22:38:45 +0000621 void sendActualWorkDuration(Duration, TimePoint) override {}
Matt Buckley06f299a2021-09-24 19:43:51 +0000622
623 bool shouldReconnectHAL() override { return false; }
624
625 std::vector<int32_t> getPowerHintSessionThreadIds() override { return std::vector<int32_t>{}; }
626
Matt Buckley2fa85012022-08-30 22:38:45 +0000627 std::optional<Duration> getTargetWorkDuration() override { return std::nullopt; }
Matt Buckley06f299a2021-09-24 19:43:51 +0000628
Dan Stoza030fbc12020-02-19 15:32:01 -0800629private:
Dan Stoza030fbc12020-02-19 15:32:01 -0800630 const sp<V1_3::IPower> mPowerHal = nullptr;
631};
632
Xiang Wange12b4fa2022-03-25 23:48:40 +0000633AidlPowerHalWrapper::AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
634 auto ret = mPowerHal->isModeSupported(Mode::EXPENSIVE_RENDERING, &mHasExpensiveRendering);
635 if (!ret.isOk()) {
636 mHasExpensiveRendering = false;
Dan Stoza030fbc12020-02-19 15:32:01 -0800637 }
638
Xiang Wange12b4fa2022-03-25 23:48:40 +0000639 ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT, &mHasDisplayUpdateImminent);
640 if (!ret.isOk()) {
641 mHasDisplayUpdateImminent = false;
Dan Stoza030fbc12020-02-19 15:32:01 -0800642 }
643
Xiang Wange12b4fa2022-03-25 23:48:40 +0000644 mSupportsPowerHint = checkPowerHintSessionSupported();
645}
Dan Stoza030fbc12020-02-19 15:32:01 -0800646
Xiang Wange12b4fa2022-03-25 23:48:40 +0000647AidlPowerHalWrapper::~AidlPowerHalWrapper() {
648 if (mPowerHintSession != nullptr) {
649 mPowerHintSession->close();
650 mPowerHintSession = nullptr;
Dan Stoza030fbc12020-02-19 15:32:01 -0800651 }
Matt Buckley50c44062022-01-17 20:48:10 +0000652}
Dan Stoza030fbc12020-02-19 15:32:01 -0800653
Xiang Wange12b4fa2022-03-25 23:48:40 +0000654std::unique_ptr<PowerAdvisor::HalWrapper> AidlPowerHalWrapper::connect() {
655 // This only waits if the service is actually declared
656 sp<IPower> powerHal = waitForVintfService<IPower>();
657 if (powerHal == nullptr) {
658 return nullptr;
659 }
660 ALOGI("Loaded AIDL Power HAL service");
661
662 return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
663}
664
665bool AidlPowerHalWrapper::setExpensiveRendering(bool enabled) {
666 ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
667 if (!mHasExpensiveRendering) {
668 ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
669 return true;
670 }
671
672 auto ret = mPowerHal->setMode(Mode::EXPENSIVE_RENDERING, enabled);
673 if (ret.isOk()) {
674 traceExpensiveRendering(enabled);
675 }
676 return ret.isOk();
677}
678
Matt Buckley15ecd1c2022-11-01 21:57:16 +0000679bool AidlPowerHalWrapper::notifyDisplayUpdateImminentAndCpuReset() {
680 ALOGV("AIDL notifyDisplayUpdateImminentAndCpuReset");
681 if (isPowerHintSessionRunning()) {
682 mPowerHintSession->sendHint(SessionHint::CPU_LOAD_RESET);
683 }
684
Xiang Wange12b4fa2022-03-25 23:48:40 +0000685 if (!mHasDisplayUpdateImminent) {
686 ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
687 return true;
688 }
689
690 auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
691 return ret.isOk();
692}
693
Matt Buckley50c44062022-01-17 20:48:10 +0000694// Only version 2+ of the aidl supports power hint sessions, hidl has no support
Xiang Wange12b4fa2022-03-25 23:48:40 +0000695bool AidlPowerHalWrapper::supportsPowerHintSession() {
696 return mSupportsPowerHint;
697}
698
699bool AidlPowerHalWrapper::checkPowerHintSessionSupported() {
700 int64_t unused;
701 // Try to get preferred rate to determine if hint sessions are supported
702 // We check for isOk not EX_UNSUPPORTED_OPERATION to lump together errors
703 return mPowerHal->getHintSessionPreferredRate(&unused).isOk();
704}
705
706bool AidlPowerHalWrapper::isPowerHintSessionRunning() {
707 return mPowerHintSession != nullptr;
708}
709
710void AidlPowerHalWrapper::closePowerHintSession() {
711 if (mPowerHintSession != nullptr) {
712 mPowerHintSession->close();
713 mPowerHintSession = nullptr;
714 }
715}
716
717void AidlPowerHalWrapper::restartPowerHintSession() {
718 closePowerHintSession();
719 startPowerHintSession();
720}
721
722void AidlPowerHalWrapper::setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) {
723 if (threadIds != mPowerHintThreadIds) {
724 mPowerHintThreadIds = threadIds;
725 if (isPowerHintSessionRunning()) {
726 restartPowerHintSession();
727 }
728 }
729}
730
731bool AidlPowerHalWrapper::startPowerHintSession() {
732 if (mPowerHintSession != nullptr || mPowerHintThreadIds.empty()) {
733 ALOGV("Cannot start power hint session, skipping");
734 return false;
735 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000736 auto ret = mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
737 mPowerHintThreadIds, mTargetDuration.ns(),
738 &mPowerHintSession);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000739 if (!ret.isOk()) {
740 ALOGW("Failed to start power hint session with error: %s",
741 ret.exceptionToString(ret.exceptionCode()).c_str());
742 } else {
743 mLastTargetDurationSent = mTargetDuration;
744 }
745 return isPowerHintSessionRunning();
746}
747
Matt Buckley2fa85012022-08-30 22:38:45 +0000748void AidlPowerHalWrapper::setTargetWorkDuration(Duration targetDuration) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000749 ATRACE_CALL();
Matt Buckley50c44062022-01-17 20:48:10 +0000750 mTargetDuration = targetDuration;
Matt Buckley2fa85012022-08-30 22:38:45 +0000751 if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration.ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000752 if (isPowerHintSessionRunning() && (targetDuration != mLastTargetDurationSent)) {
Matt Buckley2fa85012022-08-30 22:38:45 +0000753 ALOGV("Sending target time: %" PRId64 "ns", targetDuration.ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000754 mLastTargetDurationSent = targetDuration;
Matt Buckley2fa85012022-08-30 22:38:45 +0000755 auto ret = mPowerHintSession->updateTargetWorkDuration(targetDuration.ns());
Xiang Wange12b4fa2022-03-25 23:48:40 +0000756 if (!ret.isOk()) {
757 ALOGW("Failed to set power hint target work duration with error: %s",
758 ret.exceptionMessage().c_str());
759 mShouldReconnectHal = true;
760 }
761 }
762}
763
Matt Buckley2fa85012022-08-30 22:38:45 +0000764void AidlPowerHalWrapper::sendActualWorkDuration(Duration actualDuration, TimePoint timestamp) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000765 ATRACE_CALL();
Matt Buckley2fa85012022-08-30 22:38:45 +0000766 if (actualDuration < 0ns || !isPowerHintSessionRunning()) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000767 ALOGV("Failed to send actual work duration, skipping");
768 return;
769 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000770 mActualDuration = actualDuration;
Xiang Wang0aba49e2022-04-06 16:13:59 +0000771 WorkDuration duration;
Matt Buckley2fa85012022-08-30 22:38:45 +0000772 duration.durationNanos = actualDuration.ns();
773 duration.timeStampNanos = timestamp.ns();
Xiang Wange12b4fa2022-03-25 23:48:40 +0000774 mPowerHintQueue.push_back(duration);
775
Xiang Wange12b4fa2022-03-25 23:48:40 +0000776 if (sTraceHintSessionData) {
Matt Buckley2fa85012022-08-30 22:38:45 +0000777 ATRACE_INT64("Measured duration", actualDuration.ns());
778 ATRACE_INT64("Target error term", Duration{actualDuration - mTargetDuration}.ns());
Xiang Wang0aba49e2022-04-06 16:13:59 +0000779
Matt Buckley2fa85012022-08-30 22:38:45 +0000780 ATRACE_INT64("Reported duration", actualDuration.ns());
781 ATRACE_INT64("Reported target", mLastTargetDurationSent.ns());
782 ATRACE_INT64("Reported target error term",
783 Duration{actualDuration - mLastTargetDurationSent}.ns());
Xiang Wange12b4fa2022-03-25 23:48:40 +0000784 }
785
Xiang Wang0aba49e2022-04-06 16:13:59 +0000786 ALOGV("Sending actual work duration of: %" PRId64 " on reported target: %" PRId64
Xiang Wange12b4fa2022-03-25 23:48:40 +0000787 " with error: %" PRId64,
Matt Buckley2fa85012022-08-30 22:38:45 +0000788 actualDuration.ns(), mLastTargetDurationSent.ns(),
789 Duration{actualDuration - mLastTargetDurationSent}.ns());
Xiang Wange12b4fa2022-03-25 23:48:40 +0000790
Matt Buckley44e612e2022-08-30 22:02:37 +0000791 auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue);
792 if (!ret.isOk()) {
793 ALOGW("Failed to report actual work durations with error: %s",
794 ret.exceptionMessage().c_str());
795 mShouldReconnectHal = true;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000796 }
Matt Buckley44e612e2022-08-30 22:02:37 +0000797 mPowerHintQueue.clear();
Xiang Wange12b4fa2022-03-25 23:48:40 +0000798}
799
800bool AidlPowerHalWrapper::shouldReconnectHAL() {
801 return mShouldReconnectHal;
802}
803
804std::vector<int32_t> AidlPowerHalWrapper::getPowerHintSessionThreadIds() {
805 return mPowerHintThreadIds;
806}
807
Matt Buckley2fa85012022-08-30 22:38:45 +0000808std::optional<Duration> AidlPowerHalWrapper::getTargetWorkDuration() {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000809 return mTargetDuration;
810}
811
Matt Buckleyef51fba2021-10-12 19:30:12 +0000812const bool AidlPowerHalWrapper::sTraceHintSessionData =
813 base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
814
Dan Stoza030fbc12020-02-19 15:32:01 -0800815PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
Matt Buckley57274052022-08-12 21:54:23 +0000816 if (!mHasHal) {
Dan Stoza9c051c02020-02-28 10:19:07 -0800817 return nullptr;
818 }
819
Matt Buckley50c44062022-01-17 20:48:10 +0000820 // Grab old hint session values before we destroy any existing wrapper
Matt Buckley06f299a2021-09-24 19:43:51 +0000821 std::vector<int32_t> oldPowerHintSessionThreadIds;
Matt Buckley2fa85012022-08-30 22:38:45 +0000822 std::optional<Duration> oldTargetWorkDuration;
Matt Buckley06f299a2021-09-24 19:43:51 +0000823
Matt Buckley57274052022-08-12 21:54:23 +0000824 if (mHalWrapper != nullptr) {
825 oldPowerHintSessionThreadIds = mHalWrapper->getPowerHintSessionThreadIds();
826 oldTargetWorkDuration = mHalWrapper->getTargetWorkDuration();
Matt Buckley06f299a2021-09-24 19:43:51 +0000827 }
828
Dan Stoza9c051c02020-02-28 10:19:07 -0800829 // If we used to have a HAL, but it stopped responding, attempt to reconnect
Michael Wright1509a232018-06-21 02:50:34 +0100830 if (mReconnectPowerHal) {
Matt Buckley57274052022-08-12 21:54:23 +0000831 mHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100832 mReconnectPowerHal = false;
833 }
834
Matt Buckley57274052022-08-12 21:54:23 +0000835 if (mHalWrapper != nullptr) {
836 auto wrapper = mHalWrapper.get();
Matt Buckley50c44062022-01-17 20:48:10 +0000837 // If the wrapper is fine, return it, but if it indicates a reconnect, remake it
Matt Buckley06f299a2021-09-24 19:43:51 +0000838 if (!wrapper->shouldReconnectHAL()) {
839 return wrapper;
840 }
Xiang Wang65a2e6f2022-04-18 21:19:17 +0000841 ALOGD("Reconnecting Power HAL");
Matt Buckley57274052022-08-12 21:54:23 +0000842 mHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100843 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800844
Matt Buckley50c44062022-01-17 20:48:10 +0000845 // At this point, we know for sure there is no running session
Matt Buckley06f299a2021-09-24 19:43:51 +0000846 mPowerHintSessionRunning = false;
847
Dan Stoza030fbc12020-02-19 15:32:01 -0800848 // First attempt to connect to the AIDL Power HAL
Matt Buckley57274052022-08-12 21:54:23 +0000849 mHalWrapper = AidlPowerHalWrapper::connect();
Dan Stoza030fbc12020-02-19 15:32:01 -0800850
851 // If that didn't succeed, attempt to connect to the HIDL Power HAL
Matt Buckley57274052022-08-12 21:54:23 +0000852 if (mHalWrapper == nullptr) {
853 mHalWrapper = HidlPowerHalWrapper::connect();
Xiang Wang65a2e6f2022-04-18 21:19:17 +0000854 } else {
855 ALOGD("Successfully connecting AIDL Power HAL");
Matt Buckley50c44062022-01-17 20:48:10 +0000856 // If AIDL, pass on any existing hint session values
Matt Buckley57274052022-08-12 21:54:23 +0000857 mHalWrapper->setPowerHintSessionThreadIds(oldPowerHintSessionThreadIds);
Matt Buckley50c44062022-01-17 20:48:10 +0000858 // Only set duration and start if duration is defined
Matt Buckley06f299a2021-09-24 19:43:51 +0000859 if (oldTargetWorkDuration.has_value()) {
Matt Buckley57274052022-08-12 21:54:23 +0000860 mHalWrapper->setTargetWorkDuration(*oldTargetWorkDuration);
Matt Buckley50c44062022-01-17 20:48:10 +0000861 // Only start if possible to run and both threadids and duration are defined
Matt Buckley06f299a2021-09-24 19:43:51 +0000862 if (usePowerHintSession() && !oldPowerHintSessionThreadIds.empty()) {
Matt Buckley57274052022-08-12 21:54:23 +0000863 mPowerHintSessionRunning = mHalWrapper->startPowerHintSession();
Matt Buckley06f299a2021-09-24 19:43:51 +0000864 }
865 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800866 }
867
Dan Stoza9c051c02020-02-28 10:19:07 -0800868 // If we make it to this point and still don't have a HAL, it's unlikely we
869 // will, so stop trying
Matt Buckley57274052022-08-12 21:54:23 +0000870 if (mHalWrapper == nullptr) {
871 mHasHal = false;
Dan Stoza9c051c02020-02-28 10:19:07 -0800872 }
873
Matt Buckley57274052022-08-12 21:54:23 +0000874 return mHalWrapper.get();
Michael Wright1509a232018-06-21 02:50:34 +0100875}
876
877} // namespace impl
878} // namespace Hwc2
879} // namespace android