blob: 36f71bb481ae9a7c9d7ee95d7e49aaf9c1e546c0 [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 Buckleyac15a1b2023-02-28 06:51:28 +0000222 halWrapper->sendActualWorkDuration(*actualDuration + sTargetSafetyMargin,
Matt Buckley2fa85012022-08-30 22:38:45 +0000223 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 if (predictedDuration.has_value()) {
236 std::lock_guard lock(mPowerHalMutex);
237 HalWrapper* const halWrapper = getPowerHal();
238 if (halWrapper != nullptr) {
Matt Buckleyac15a1b2023-02-28 06:51:28 +0000239 halWrapper->sendActualWorkDuration(*predictedDuration + sTargetSafetyMargin,
Matt Buckley2fa85012022-08-30 22:38:45 +0000240 TimePoint::now());
Matt Buckley50c44062022-01-17 20:48:10 +0000241 }
242 }
243}
244
Matt Buckley06f299a2021-09-24 19:43:51 +0000245void PowerAdvisor::enablePowerHint(bool enabled) {
246 mPowerHintEnabled = enabled;
247}
248
Matt Buckleyef51fba2021-10-12 19:30:12 +0000249bool PowerAdvisor::startPowerHintSession(const std::vector<int32_t>& threadIds) {
250 if (!usePowerHintSession()) {
251 ALOGI("Power hint session cannot be started, skipping");
252 }
253 {
254 std::lock_guard lock(mPowerHalMutex);
255 HalWrapper* halWrapper = getPowerHal();
256 if (halWrapper != nullptr && usePowerHintSession()) {
257 halWrapper->setPowerHintSessionThreadIds(threadIds);
258 mPowerHintSessionRunning = halWrapper->startPowerHintSession();
259 }
260 }
261 return mPowerHintSessionRunning;
262}
263
Matt Buckley50c44062022-01-17 20:48:10 +0000264void PowerAdvisor::setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime) {
265 DisplayTimingData& displayData = mDisplayTimingData[displayId];
266 if (displayData.gpuEndFenceTime) {
267 nsecs_t signalTime = displayData.gpuEndFenceTime->getSignalTime();
268 if (signalTime != Fence::SIGNAL_TIME_INVALID && signalTime != Fence::SIGNAL_TIME_PENDING) {
269 for (auto&& [_, otherDisplayData] : mDisplayTimingData) {
270 // If the previous display started before us but ended after we should have
271 // started, then it likely delayed our start time and we must compensate for that.
272 // Displays finishing earlier should have already made their way through this call
273 // and swapped their timing into "lastValid" from "latest", so we check that here.
274 if (!otherDisplayData.lastValidGpuStartTime.has_value()) continue;
275 if ((*otherDisplayData.lastValidGpuStartTime < *displayData.gpuStartTime) &&
276 (*otherDisplayData.lastValidGpuEndTime > *displayData.gpuStartTime)) {
277 displayData.lastValidGpuStartTime = *otherDisplayData.lastValidGpuEndTime;
278 break;
279 }
280 }
281 displayData.lastValidGpuStartTime = displayData.gpuStartTime;
Matt Buckley2fa85012022-08-30 22:38:45 +0000282 displayData.lastValidGpuEndTime = TimePoint::fromNs(signalTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000283 }
284 }
285 displayData.gpuEndFenceTime = std::move(fenceTime);
Matt Buckley2fa85012022-08-30 22:38:45 +0000286 displayData.gpuStartTime = TimePoint::now();
Matt Buckley50c44062022-01-17 20:48:10 +0000287}
288
Matt Buckley2fa85012022-08-30 22:38:45 +0000289void PowerAdvisor::setHwcValidateTiming(DisplayId displayId, TimePoint validateStartTime,
290 TimePoint validateEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000291 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000292 displayData.hwcValidateStartTime = validateStartTime;
293 displayData.hwcValidateEndTime = validateEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000294}
295
Matt Buckley2fa85012022-08-30 22:38:45 +0000296void PowerAdvisor::setHwcPresentTiming(DisplayId displayId, TimePoint presentStartTime,
297 TimePoint presentEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000298 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000299 displayData.hwcPresentStartTime = presentStartTime;
300 displayData.hwcPresentEndTime = presentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000301}
302
303void PowerAdvisor::setSkippedValidate(DisplayId displayId, bool skipped) {
304 mDisplayTimingData[displayId].skippedValidate = skipped;
305}
306
307void PowerAdvisor::setRequiresClientComposition(DisplayId displayId,
308 bool requiresClientComposition) {
309 mDisplayTimingData[displayId].usedClientComposition = requiresClientComposition;
310}
311
Matt Buckley2fa85012022-08-30 22:38:45 +0000312void PowerAdvisor::setExpectedPresentTime(TimePoint expectedPresentTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000313 mExpectedPresentTimes.append(expectedPresentTime);
314}
315
Matt Buckley2fa85012022-08-30 22:38:45 +0000316void PowerAdvisor::setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) {
Matt Buckley1809d902022-08-05 06:51:43 +0000317 mLastSfPresentEndTime = presentEndTime;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700318 mLastPresentFenceTime = presentFenceTime;
319}
320
Matt Buckley2fa85012022-08-30 22:38:45 +0000321void PowerAdvisor::setFrameDelay(Duration frameDelayDuration) {
Matt Buckley50c44062022-01-17 20:48:10 +0000322 mFrameDelayDuration = frameDelayDuration;
323}
324
Matt Buckley2fa85012022-08-30 22:38:45 +0000325void PowerAdvisor::setHwcPresentDelayedTime(DisplayId displayId, TimePoint earliestFrameStartTime) {
326 mDisplayTimingData[displayId].hwcPresentDelayedTime = earliestFrameStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000327}
328
Matt Buckley2fa85012022-08-30 22:38:45 +0000329void PowerAdvisor::setCommitStart(TimePoint commitStartTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000330 mCommitStartTimes.append(commitStartTime);
331}
332
Matt Buckley2fa85012022-08-30 22:38:45 +0000333void PowerAdvisor::setCompositeEnd(TimePoint compositeEndTime) {
334 mLastPostcompDuration = compositeEndTime - mLastSfPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000335}
336
337void PowerAdvisor::setDisplays(std::vector<DisplayId>& displayIds) {
338 mDisplayIds = displayIds;
339}
340
Matt Buckley2fa85012022-08-30 22:38:45 +0000341void PowerAdvisor::setTotalFrameTargetWorkDuration(Duration targetDuration) {
Matt Buckley50c44062022-01-17 20:48:10 +0000342 mTotalFrameTargetDuration = targetDuration;
343}
344
345std::vector<DisplayId> PowerAdvisor::getOrderedDisplayIds(
Matt Buckley2fa85012022-08-30 22:38:45 +0000346 std::optional<TimePoint> DisplayTimingData::*sortBy) {
Matt Buckley50c44062022-01-17 20:48:10 +0000347 std::vector<DisplayId> sortedDisplays;
348 std::copy_if(mDisplayIds.begin(), mDisplayIds.end(), std::back_inserter(sortedDisplays),
349 [&](DisplayId id) {
350 return mDisplayTimingData.count(id) &&
351 (mDisplayTimingData[id].*sortBy).has_value();
352 });
353 std::sort(sortedDisplays.begin(), sortedDisplays.end(), [&](DisplayId idA, DisplayId idB) {
354 return *(mDisplayTimingData[idA].*sortBy) < *(mDisplayTimingData[idB].*sortBy);
355 });
356 return sortedDisplays;
357}
358
Matt Buckley2fa85012022-08-30 22:38:45 +0000359std::optional<Duration> PowerAdvisor::estimateWorkDuration(bool earlyHint) {
Matt Buckley50c44062022-01-17 20:48:10 +0000360 if (earlyHint && (!mExpectedPresentTimes.isFull() || !mCommitStartTimes.isFull())) {
361 return std::nullopt;
362 }
363
364 // Tracks when we finish presenting to hwc
Matt Buckley2fa85012022-08-30 22:38:45 +0000365 TimePoint estimatedEndTime = mCommitStartTimes[0];
Matt Buckley50c44062022-01-17 20:48:10 +0000366
367 // How long we spent this frame not doing anything, waiting for fences or vsync
Matt Buckley2fa85012022-08-30 22:38:45 +0000368 Duration idleDuration = 0ns;
Matt Buckley50c44062022-01-17 20:48:10 +0000369
370 // Most recent previous gpu end time in the current frame, probably from a prior display, used
371 // 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 +0000372 std::optional<TimePoint> previousValidGpuEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000373
374 // The currently estimated gpu end time for the frame,
375 // used to accumulate gpu time as we iterate over the active displays
Matt Buckley2fa85012022-08-30 22:38:45 +0000376 std::optional<TimePoint> estimatedGpuEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000377
378 // If we're predicting at the start of the frame, we use last frame as our reference point
379 // 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 +0000380 TimePoint referenceFrameStartTime = (earlyHint ? mCommitStartTimes[-1] : mCommitStartTimes[0]);
Matt Buckley50c44062022-01-17 20:48:10 +0000381
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700382 // When the prior frame should be presenting to the display
383 // If we're predicting at the start of the frame, we use last frame's expected present time
384 // If we're predicting at the end of the frame, the present fence time is already known
Matt Buckley2fa85012022-08-30 22:38:45 +0000385 TimePoint lastFramePresentTime =
386 (earlyHint ? mExpectedPresentTimes[-1] : mLastPresentFenceTime);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700387
Matt Buckley50c44062022-01-17 20:48:10 +0000388 // The timing info for the previously calculated display, if there was one
389 std::optional<DisplayTimeline> previousDisplayReferenceTiming;
390 std::vector<DisplayId>&& displayIds =
Matt Buckley16dec1f2022-06-07 21:46:20 +0000391 getOrderedDisplayIds(&DisplayTimingData::hwcPresentStartTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000392 DisplayTimeline referenceTiming, estimatedTiming;
393
Matt Buckley1809d902022-08-05 06:51:43 +0000394 // Iterate over the displays that use hwc in the same order they are presented
Matt Buckley50c44062022-01-17 20:48:10 +0000395 for (DisplayId displayId : displayIds) {
396 if (mDisplayTimingData.count(displayId) == 0) {
397 continue;
398 }
399
400 auto& displayData = mDisplayTimingData.at(displayId);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700401
402 // mLastPresentFenceTime should always be the time of the reference frame, since it will be
403 // the previous frame's present fence if called at the start, and current frame's if called
404 // at the end
405 referenceTiming = displayData.calculateDisplayTimeline(mLastPresentFenceTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000406
Matt Buckley16dec1f2022-06-07 21:46:20 +0000407 // If this is the first display, include the duration before hwc present starts
Matt Buckley50c44062022-01-17 20:48:10 +0000408 if (!previousDisplayReferenceTiming.has_value()) {
Matt Buckley16dec1f2022-06-07 21:46:20 +0000409 estimatedEndTime += referenceTiming.hwcPresentStartTime - referenceFrameStartTime;
410 } else { // Otherwise add the time since last display's hwc present finished
411 estimatedEndTime += referenceTiming.hwcPresentStartTime -
412 previousDisplayReferenceTiming->hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000413 }
414
Matt Buckley50689e82022-06-21 13:23:27 -0700415 // Late hint can re-use reference timing here since it's estimating its own reference frame
416 estimatedTiming = earlyHint
417 ? referenceTiming.estimateTimelineFromReference(lastFramePresentTime,
418 estimatedEndTime)
419 : referenceTiming;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700420
Matt Buckley50c44062022-01-17 20:48:10 +0000421 // Update predicted present finish time with this display's present time
Matt Buckley16dec1f2022-06-07 21:46:20 +0000422 estimatedEndTime = estimatedTiming.hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000423
424 // Track how long we spent waiting for the fence, can be excluded from the timing estimate
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700425 idleDuration += estimatedTiming.probablyWaitsForPresentFence
426 ? lastFramePresentTime - estimatedTiming.presentFenceWaitStartTime
Matt Buckley2fa85012022-08-30 22:38:45 +0000427 : 0ns;
Matt Buckley50c44062022-01-17 20:48:10 +0000428
429 // Track how long we spent waiting to present, can be excluded from the timing estimate
Matt Buckley2fa85012022-08-30 22:38:45 +0000430 idleDuration += earlyHint ? 0ns : referenceTiming.hwcPresentDelayDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000431
432 // Estimate the reference frame's gpu timing
433 auto gpuTiming = displayData.estimateGpuTiming(previousValidGpuEndTime);
434 if (gpuTiming.has_value()) {
435 previousValidGpuEndTime = gpuTiming->startTime + gpuTiming->duration;
436
437 // Estimate the prediction frame's gpu end time from the reference frame
Matt Buckley2fa85012022-08-30 22:38:45 +0000438 estimatedGpuEndTime = std::max(estimatedTiming.hwcPresentStartTime,
439 estimatedGpuEndTime.value_or(TimePoint{0ns})) +
Matt Buckley50c44062022-01-17 20:48:10 +0000440 gpuTiming->duration;
441 }
442 previousDisplayReferenceTiming = referenceTiming;
443 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000444 ATRACE_INT64("Idle duration", idleDuration.ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000445
Matt Buckley2fa85012022-08-30 22:38:45 +0000446 TimePoint estimatedFlingerEndTime = earlyHint ? estimatedEndTime : mLastSfPresentEndTime;
Matt Buckley1809d902022-08-05 06:51:43 +0000447
Matt Buckley50c44062022-01-17 20:48:10 +0000448 // Don't count time spent idly waiting in the estimate as we could do more work in that time
449 estimatedEndTime -= idleDuration;
Matt Buckley1809d902022-08-05 06:51:43 +0000450 estimatedFlingerEndTime -= idleDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000451
452 // We finish the frame when both present and the gpu are done, so wait for the later of the two
453 // Also add the frame delay duration since the target did not move while we were delayed
Matt Buckley2fa85012022-08-30 22:38:45 +0000454 Duration totalDuration = mFrameDelayDuration +
455 std::max(estimatedEndTime, estimatedGpuEndTime.value_or(TimePoint{0ns})) -
456 mCommitStartTimes[0];
Matt Buckley50c44062022-01-17 20:48:10 +0000457
458 // We finish SurfaceFlinger when post-composition finishes, so add that in here
Matt Buckley2fa85012022-08-30 22:38:45 +0000459 Duration flingerDuration =
Matt Buckley1809d902022-08-05 06:51:43 +0000460 estimatedFlingerEndTime + mLastPostcompDuration - mCommitStartTimes[0];
461
462 // Combine the two timings into a single normalized one
Matt Buckley2fa85012022-08-30 22:38:45 +0000463 Duration combinedDuration = combineTimingEstimates(totalDuration, flingerDuration);
Matt Buckley50c44062022-01-17 20:48:10 +0000464
465 return std::make_optional(combinedDuration);
466}
467
Matt Buckley2fa85012022-08-30 22:38:45 +0000468Duration PowerAdvisor::combineTimingEstimates(Duration totalDuration, Duration flingerDuration) {
469 Duration targetDuration{0ns};
Matt Buckley50c44062022-01-17 20:48:10 +0000470 {
471 std::lock_guard lock(mPowerHalMutex);
472 targetDuration = *getPowerHal()->getTargetWorkDuration();
473 }
474 if (!mTotalFrameTargetDuration.has_value()) return flingerDuration;
475
476 // Normalize total to the flinger target (vsync period) since that's how often we actually send
477 // hints
Matt Buckley2fa85012022-08-30 22:38:45 +0000478 Duration normalizedTotalDuration = Duration::fromNs((targetDuration.ns() * totalDuration.ns()) /
479 mTotalFrameTargetDuration->ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000480 return std::max(flingerDuration, normalizedTotalDuration);
481}
482
483PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimeline::estimateTimelineFromReference(
Matt Buckley2fa85012022-08-30 22:38:45 +0000484 TimePoint fenceTime, TimePoint displayStartTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000485 DisplayTimeline estimated;
Matt Buckley16dec1f2022-06-07 21:46:20 +0000486 estimated.hwcPresentStartTime = displayStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000487
488 // We don't predict waiting for vsync alignment yet
Matt Buckley2fa85012022-08-30 22:38:45 +0000489 estimated.hwcPresentDelayDuration = 0ns;
Matt Buckley50c44062022-01-17 20:48:10 +0000490
Matt Buckley50c44062022-01-17 20:48:10 +0000491 // How long we expect to run before we start waiting for the fence
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700492 // For now just re-use last frame's post-present duration and assume it will not change much
493 // Excludes time spent waiting for vsync since that's not going to be consistent
494 estimated.presentFenceWaitStartTime = estimated.hwcPresentStartTime +
495 (presentFenceWaitStartTime - (hwcPresentStartTime + hwcPresentDelayDuration));
496 estimated.probablyWaitsForPresentFence = fenceTime > estimated.presentFenceWaitStartTime;
497 estimated.hwcPresentEndTime = postPresentFenceHwcPresentDuration +
498 (estimated.probablyWaitsForPresentFence ? fenceTime
499 : estimated.presentFenceWaitStartTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000500 return estimated;
501}
502
503PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimingData::calculateDisplayTimeline(
Matt Buckley2fa85012022-08-30 22:38:45 +0000504 TimePoint fenceTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000505 DisplayTimeline timeline;
Matt Buckley16dec1f2022-06-07 21:46:20 +0000506 // How long between calling hwc present and trying to wait on the fence
Matt Buckley2fa85012022-08-30 22:38:45 +0000507 const Duration fenceWaitStartDelay =
508 (skippedValidate ? kFenceWaitStartDelaySkippedValidate : kFenceWaitStartDelayValidated);
Matt Buckley50c44062022-01-17 20:48:10 +0000509
Matt Buckley16dec1f2022-06-07 21:46:20 +0000510 // Did our reference frame wait for an appropriate vsync before calling into hwc
511 const bool waitedOnHwcPresentTime = hwcPresentDelayedTime.has_value() &&
512 *hwcPresentDelayedTime > *hwcPresentStartTime &&
513 *hwcPresentDelayedTime < *hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000514
515 // Use validate start here if we skipped it because we did validate + present together
Matt Buckley16dec1f2022-06-07 21:46:20 +0000516 timeline.hwcPresentStartTime = skippedValidate ? *hwcValidateStartTime : *hwcPresentStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000517
518 // Use validate end here if we skipped it because we did validate + present together
Matt Buckley16dec1f2022-06-07 21:46:20 +0000519 timeline.hwcPresentEndTime = skippedValidate ? *hwcValidateEndTime : *hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000520
Matt Buckley16dec1f2022-06-07 21:46:20 +0000521 // How long hwc present was delayed waiting for the next appropriate vsync
522 timeline.hwcPresentDelayDuration =
Matt Buckley2fa85012022-08-30 22:38:45 +0000523 (waitedOnHwcPresentTime ? *hwcPresentDelayedTime - *hwcPresentStartTime : 0ns);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700524 // When we started waiting for the present fence after calling into hwc present
525 timeline.presentFenceWaitStartTime =
Matt Buckley16dec1f2022-06-07 21:46:20 +0000526 timeline.hwcPresentStartTime + timeline.hwcPresentDelayDuration + fenceWaitStartDelay;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700527 timeline.probablyWaitsForPresentFence = fenceTime > timeline.presentFenceWaitStartTime &&
Matt Buckley16dec1f2022-06-07 21:46:20 +0000528 fenceTime < timeline.hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000529
Matt Buckley16dec1f2022-06-07 21:46:20 +0000530 // How long we ran after we finished waiting for the fence but before hwc present finished
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700531 timeline.postPresentFenceHwcPresentDuration = timeline.hwcPresentEndTime -
532 (timeline.probablyWaitsForPresentFence ? fenceTime
533 : timeline.presentFenceWaitStartTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000534 return timeline;
535}
536
537std::optional<PowerAdvisor::GpuTimeline> PowerAdvisor::DisplayTimingData::estimateGpuTiming(
Matt Buckley2fa85012022-08-30 22:38:45 +0000538 std::optional<TimePoint> previousEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000539 if (!(usedClientComposition && lastValidGpuStartTime.has_value() && gpuEndFenceTime)) {
540 return std::nullopt;
541 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000542 const TimePoint latestGpuStartTime =
543 std::max(previousEndTime.value_or(TimePoint{0ns}), *gpuStartTime);
544 const nsecs_t gpuEndFenceSignal = gpuEndFenceTime->getSignalTime();
545 Duration gpuDuration{0ns};
546 if (gpuEndFenceSignal != Fence::SIGNAL_TIME_INVALID &&
547 gpuEndFenceSignal != Fence::SIGNAL_TIME_PENDING) {
548 const TimePoint latestGpuEndTime = TimePoint::fromNs(gpuEndFenceSignal);
549
Matt Buckley50c44062022-01-17 20:48:10 +0000550 // If we know how long the most recent gpu duration was, use that
551 gpuDuration = latestGpuEndTime - latestGpuStartTime;
552 } else if (lastValidGpuEndTime.has_value()) {
553 // If we don't have the fence data, use the most recent information we do have
554 gpuDuration = *lastValidGpuEndTime - *lastValidGpuStartTime;
Matt Buckley2fa85012022-08-30 22:38:45 +0000555 if (gpuEndFenceSignal == Fence::SIGNAL_TIME_PENDING) {
Matt Buckley50c44062022-01-17 20:48:10 +0000556 // If pending but went over the previous duration, use current time as the end
Matt Buckley2fa85012022-08-30 22:38:45 +0000557 gpuDuration = std::max(gpuDuration, Duration{TimePoint::now() - latestGpuStartTime});
Matt Buckley50c44062022-01-17 20:48:10 +0000558 }
559 }
560 return GpuTimeline{.duration = gpuDuration, .startTime = latestGpuStartTime};
561}
562
Dan Stoza030fbc12020-02-19 15:32:01 -0800563class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
564public:
565 HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
566
567 ~HidlPowerHalWrapper() override = default;
568
569 static std::unique_ptr<HalWrapper> connect() {
570 // Power HAL 1.3 is not guaranteed to be available, thus we need to query
571 // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
Dan Stoza030fbc12020-02-19 15:32:01 -0800572 sp<V1_3::IPower> powerHal = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800573 sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
574 if (powerHal_1_0 != nullptr) {
575 // Try to cast to Power HAL 1.3
576 powerHal = V1_3::IPower::castFrom(powerHal_1_0);
577 if (powerHal == nullptr) {
578 ALOGW("No Power HAL 1.3 service in system, disabling PowerAdvisor");
579 } else {
580 ALOGI("Loaded Power HAL 1.3 service");
Dan Stoza030fbc12020-02-19 15:32:01 -0800581 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800582 } else {
583 ALOGW("No Power HAL found, disabling PowerAdvisor");
Dan Stoza030fbc12020-02-19 15:32:01 -0800584 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800585
Dan Stoza030fbc12020-02-19 15:32:01 -0800586 if (powerHal == nullptr) {
587 return nullptr;
588 }
589
590 return std::make_unique<HidlPowerHalWrapper>(std::move(powerHal));
591 }
592
593 bool setExpensiveRendering(bool enabled) override {
594 ALOGV("HIDL setExpensiveRendering %s", enabled ? "T" : "F");
595 auto ret = mPowerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING, enabled);
Ady Abrahamabce1652022-02-24 10:51:19 -0800596 if (ret.isOk()) {
597 traceExpensiveRendering(enabled);
598 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800599 return ret.isOk();
600 }
601
Matt Buckley15ecd1c2022-11-01 21:57:16 +0000602 bool notifyDisplayUpdateImminentAndCpuReset() override {
Dan Stoza030fbc12020-02-19 15:32:01 -0800603 // Power HAL 1.x doesn't have a notification for this
604 ALOGV("HIDL notifyUpdateImminent received but can't send");
605 return true;
606 }
607
Matt Buckley06f299a2021-09-24 19:43:51 +0000608 bool supportsPowerHintSession() override { return false; }
609
610 bool isPowerHintSessionRunning() override { return false; }
611
612 void restartPowerHintSession() override {}
613
614 void setPowerHintSessionThreadIds(const std::vector<int32_t>&) override {}
615
616 bool startPowerHintSession() override { return false; }
617
Matt Buckley2fa85012022-08-30 22:38:45 +0000618 void setTargetWorkDuration(Duration) override {}
Matt Buckley06f299a2021-09-24 19:43:51 +0000619
Matt Buckley2fa85012022-08-30 22:38:45 +0000620 void sendActualWorkDuration(Duration, TimePoint) override {}
Matt Buckley06f299a2021-09-24 19:43:51 +0000621
622 bool shouldReconnectHAL() override { return false; }
623
624 std::vector<int32_t> getPowerHintSessionThreadIds() override { return std::vector<int32_t>{}; }
625
Matt Buckley2fa85012022-08-30 22:38:45 +0000626 std::optional<Duration> getTargetWorkDuration() override { return std::nullopt; }
Matt Buckley06f299a2021-09-24 19:43:51 +0000627
Dan Stoza030fbc12020-02-19 15:32:01 -0800628private:
Dan Stoza030fbc12020-02-19 15:32:01 -0800629 const sp<V1_3::IPower> mPowerHal = nullptr;
630};
631
Xiang Wange12b4fa2022-03-25 23:48:40 +0000632AidlPowerHalWrapper::AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
633 auto ret = mPowerHal->isModeSupported(Mode::EXPENSIVE_RENDERING, &mHasExpensiveRendering);
634 if (!ret.isOk()) {
635 mHasExpensiveRendering = false;
Dan Stoza030fbc12020-02-19 15:32:01 -0800636 }
637
Xiang Wange12b4fa2022-03-25 23:48:40 +0000638 ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT, &mHasDisplayUpdateImminent);
639 if (!ret.isOk()) {
640 mHasDisplayUpdateImminent = false;
Dan Stoza030fbc12020-02-19 15:32:01 -0800641 }
642
Xiang Wange12b4fa2022-03-25 23:48:40 +0000643 mSupportsPowerHint = checkPowerHintSessionSupported();
644}
Dan Stoza030fbc12020-02-19 15:32:01 -0800645
Xiang Wange12b4fa2022-03-25 23:48:40 +0000646AidlPowerHalWrapper::~AidlPowerHalWrapper() {
647 if (mPowerHintSession != nullptr) {
648 mPowerHintSession->close();
649 mPowerHintSession = nullptr;
Dan Stoza030fbc12020-02-19 15:32:01 -0800650 }
Matt Buckley50c44062022-01-17 20:48:10 +0000651}
Dan Stoza030fbc12020-02-19 15:32:01 -0800652
Xiang Wange12b4fa2022-03-25 23:48:40 +0000653std::unique_ptr<PowerAdvisor::HalWrapper> AidlPowerHalWrapper::connect() {
654 // This only waits if the service is actually declared
655 sp<IPower> powerHal = waitForVintfService<IPower>();
656 if (powerHal == nullptr) {
657 return nullptr;
658 }
659 ALOGI("Loaded AIDL Power HAL service");
660
661 return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
662}
663
664bool AidlPowerHalWrapper::setExpensiveRendering(bool enabled) {
665 ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
666 if (!mHasExpensiveRendering) {
667 ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
668 return true;
669 }
670
671 auto ret = mPowerHal->setMode(Mode::EXPENSIVE_RENDERING, enabled);
672 if (ret.isOk()) {
673 traceExpensiveRendering(enabled);
674 }
675 return ret.isOk();
676}
677
Matt Buckley15ecd1c2022-11-01 21:57:16 +0000678bool AidlPowerHalWrapper::notifyDisplayUpdateImminentAndCpuReset() {
679 ALOGV("AIDL notifyDisplayUpdateImminentAndCpuReset");
680 if (isPowerHintSessionRunning()) {
681 mPowerHintSession->sendHint(SessionHint::CPU_LOAD_RESET);
682 }
683
Xiang Wange12b4fa2022-03-25 23:48:40 +0000684 if (!mHasDisplayUpdateImminent) {
685 ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
686 return true;
687 }
688
689 auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
690 return ret.isOk();
691}
692
Matt Buckley50c44062022-01-17 20:48:10 +0000693// Only version 2+ of the aidl supports power hint sessions, hidl has no support
Xiang Wange12b4fa2022-03-25 23:48:40 +0000694bool AidlPowerHalWrapper::supportsPowerHintSession() {
695 return mSupportsPowerHint;
696}
697
698bool AidlPowerHalWrapper::checkPowerHintSessionSupported() {
699 int64_t unused;
700 // Try to get preferred rate to determine if hint sessions are supported
701 // We check for isOk not EX_UNSUPPORTED_OPERATION to lump together errors
702 return mPowerHal->getHintSessionPreferredRate(&unused).isOk();
703}
704
705bool AidlPowerHalWrapper::isPowerHintSessionRunning() {
706 return mPowerHintSession != nullptr;
707}
708
709void AidlPowerHalWrapper::closePowerHintSession() {
710 if (mPowerHintSession != nullptr) {
711 mPowerHintSession->close();
712 mPowerHintSession = nullptr;
713 }
714}
715
716void AidlPowerHalWrapper::restartPowerHintSession() {
717 closePowerHintSession();
718 startPowerHintSession();
719}
720
721void AidlPowerHalWrapper::setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) {
722 if (threadIds != mPowerHintThreadIds) {
723 mPowerHintThreadIds = threadIds;
724 if (isPowerHintSessionRunning()) {
725 restartPowerHintSession();
726 }
727 }
728}
729
730bool AidlPowerHalWrapper::startPowerHintSession() {
731 if (mPowerHintSession != nullptr || mPowerHintThreadIds.empty()) {
732 ALOGV("Cannot start power hint session, skipping");
733 return false;
734 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000735 auto ret = mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
736 mPowerHintThreadIds, mTargetDuration.ns(),
737 &mPowerHintSession);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000738 if (!ret.isOk()) {
739 ALOGW("Failed to start power hint session with error: %s",
740 ret.exceptionToString(ret.exceptionCode()).c_str());
741 } else {
742 mLastTargetDurationSent = mTargetDuration;
743 }
744 return isPowerHintSessionRunning();
745}
746
Matt Buckley2fa85012022-08-30 22:38:45 +0000747void AidlPowerHalWrapper::setTargetWorkDuration(Duration targetDuration) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000748 ATRACE_CALL();
Matt Buckley50c44062022-01-17 20:48:10 +0000749 mTargetDuration = targetDuration;
Matt Buckley2fa85012022-08-30 22:38:45 +0000750 if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration.ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000751 if (isPowerHintSessionRunning() && (targetDuration != mLastTargetDurationSent)) {
Matt Buckley2fa85012022-08-30 22:38:45 +0000752 ALOGV("Sending target time: %" PRId64 "ns", targetDuration.ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000753 mLastTargetDurationSent = targetDuration;
Matt Buckley2fa85012022-08-30 22:38:45 +0000754 auto ret = mPowerHintSession->updateTargetWorkDuration(targetDuration.ns());
Xiang Wange12b4fa2022-03-25 23:48:40 +0000755 if (!ret.isOk()) {
756 ALOGW("Failed to set power hint target work duration with error: %s",
757 ret.exceptionMessage().c_str());
758 mShouldReconnectHal = true;
759 }
760 }
761}
762
Matt Buckley2fa85012022-08-30 22:38:45 +0000763void AidlPowerHalWrapper::sendActualWorkDuration(Duration actualDuration, TimePoint timestamp) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000764 ATRACE_CALL();
Matt Buckley2fa85012022-08-30 22:38:45 +0000765 if (actualDuration < 0ns || !isPowerHintSessionRunning()) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000766 ALOGV("Failed to send actual work duration, skipping");
767 return;
768 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000769 mActualDuration = actualDuration;
Xiang Wang0aba49e2022-04-06 16:13:59 +0000770 WorkDuration duration;
Matt Buckley2fa85012022-08-30 22:38:45 +0000771 duration.durationNanos = actualDuration.ns();
772 duration.timeStampNanos = timestamp.ns();
Xiang Wange12b4fa2022-03-25 23:48:40 +0000773 mPowerHintQueue.push_back(duration);
774
Xiang Wange12b4fa2022-03-25 23:48:40 +0000775 if (sTraceHintSessionData) {
Matt Buckley2fa85012022-08-30 22:38:45 +0000776 ATRACE_INT64("Measured duration", actualDuration.ns());
777 ATRACE_INT64("Target error term", Duration{actualDuration - mTargetDuration}.ns());
Xiang Wang0aba49e2022-04-06 16:13:59 +0000778
Matt Buckley2fa85012022-08-30 22:38:45 +0000779 ATRACE_INT64("Reported duration", actualDuration.ns());
780 ATRACE_INT64("Reported target", mLastTargetDurationSent.ns());
781 ATRACE_INT64("Reported target error term",
782 Duration{actualDuration - mLastTargetDurationSent}.ns());
Xiang Wange12b4fa2022-03-25 23:48:40 +0000783 }
784
Xiang Wang0aba49e2022-04-06 16:13:59 +0000785 ALOGV("Sending actual work duration of: %" PRId64 " on reported target: %" PRId64
Xiang Wange12b4fa2022-03-25 23:48:40 +0000786 " with error: %" PRId64,
Matt Buckley2fa85012022-08-30 22:38:45 +0000787 actualDuration.ns(), mLastTargetDurationSent.ns(),
788 Duration{actualDuration - mLastTargetDurationSent}.ns());
Xiang Wange12b4fa2022-03-25 23:48:40 +0000789
Matt Buckley44e612e2022-08-30 22:02:37 +0000790 auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue);
791 if (!ret.isOk()) {
792 ALOGW("Failed to report actual work durations with error: %s",
793 ret.exceptionMessage().c_str());
794 mShouldReconnectHal = true;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000795 }
Matt Buckley44e612e2022-08-30 22:02:37 +0000796 mPowerHintQueue.clear();
Xiang Wange12b4fa2022-03-25 23:48:40 +0000797}
798
799bool AidlPowerHalWrapper::shouldReconnectHAL() {
800 return mShouldReconnectHal;
801}
802
803std::vector<int32_t> AidlPowerHalWrapper::getPowerHintSessionThreadIds() {
804 return mPowerHintThreadIds;
805}
806
Matt Buckley2fa85012022-08-30 22:38:45 +0000807std::optional<Duration> AidlPowerHalWrapper::getTargetWorkDuration() {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000808 return mTargetDuration;
809}
810
Matt Buckleyef51fba2021-10-12 19:30:12 +0000811const bool AidlPowerHalWrapper::sTraceHintSessionData =
812 base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
813
Matt Buckleyac15a1b2023-02-28 06:51:28 +0000814const Duration PowerAdvisor::sTargetSafetyMargin = std::chrono::microseconds(
815 base::GetIntProperty<int64_t>("debug.sf.hint_margin_us",
816 ticks<std::micro>(PowerAdvisor::kDefaultTargetSafetyMargin)));
817
Dan Stoza030fbc12020-02-19 15:32:01 -0800818PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
Matt Buckley57274052022-08-12 21:54:23 +0000819 if (!mHasHal) {
Dan Stoza9c051c02020-02-28 10:19:07 -0800820 return nullptr;
821 }
822
Matt Buckley50c44062022-01-17 20:48:10 +0000823 // Grab old hint session values before we destroy any existing wrapper
Matt Buckley06f299a2021-09-24 19:43:51 +0000824 std::vector<int32_t> oldPowerHintSessionThreadIds;
Matt Buckley2fa85012022-08-30 22:38:45 +0000825 std::optional<Duration> oldTargetWorkDuration;
Matt Buckley06f299a2021-09-24 19:43:51 +0000826
Matt Buckley57274052022-08-12 21:54:23 +0000827 if (mHalWrapper != nullptr) {
828 oldPowerHintSessionThreadIds = mHalWrapper->getPowerHintSessionThreadIds();
829 oldTargetWorkDuration = mHalWrapper->getTargetWorkDuration();
Matt Buckley06f299a2021-09-24 19:43:51 +0000830 }
831
Dan Stoza9c051c02020-02-28 10:19:07 -0800832 // If we used to have a HAL, but it stopped responding, attempt to reconnect
Michael Wright1509a232018-06-21 02:50:34 +0100833 if (mReconnectPowerHal) {
Matt Buckley57274052022-08-12 21:54:23 +0000834 mHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100835 mReconnectPowerHal = false;
836 }
837
Matt Buckley57274052022-08-12 21:54:23 +0000838 if (mHalWrapper != nullptr) {
839 auto wrapper = mHalWrapper.get();
Matt Buckley50c44062022-01-17 20:48:10 +0000840 // If the wrapper is fine, return it, but if it indicates a reconnect, remake it
Matt Buckley06f299a2021-09-24 19:43:51 +0000841 if (!wrapper->shouldReconnectHAL()) {
842 return wrapper;
843 }
Xiang Wang65a2e6f2022-04-18 21:19:17 +0000844 ALOGD("Reconnecting Power HAL");
Matt Buckley57274052022-08-12 21:54:23 +0000845 mHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100846 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800847
Matt Buckley50c44062022-01-17 20:48:10 +0000848 // At this point, we know for sure there is no running session
Matt Buckley06f299a2021-09-24 19:43:51 +0000849 mPowerHintSessionRunning = false;
850
Dan Stoza030fbc12020-02-19 15:32:01 -0800851 // First attempt to connect to the AIDL Power HAL
Matt Buckley57274052022-08-12 21:54:23 +0000852 mHalWrapper = AidlPowerHalWrapper::connect();
Dan Stoza030fbc12020-02-19 15:32:01 -0800853
854 // If that didn't succeed, attempt to connect to the HIDL Power HAL
Matt Buckley57274052022-08-12 21:54:23 +0000855 if (mHalWrapper == nullptr) {
856 mHalWrapper = HidlPowerHalWrapper::connect();
Xiang Wang65a2e6f2022-04-18 21:19:17 +0000857 } else {
858 ALOGD("Successfully connecting AIDL Power HAL");
Matt Buckley50c44062022-01-17 20:48:10 +0000859 // If AIDL, pass on any existing hint session values
Matt Buckley57274052022-08-12 21:54:23 +0000860 mHalWrapper->setPowerHintSessionThreadIds(oldPowerHintSessionThreadIds);
Matt Buckley50c44062022-01-17 20:48:10 +0000861 // Only set duration and start if duration is defined
Matt Buckley06f299a2021-09-24 19:43:51 +0000862 if (oldTargetWorkDuration.has_value()) {
Matt Buckley57274052022-08-12 21:54:23 +0000863 mHalWrapper->setTargetWorkDuration(*oldTargetWorkDuration);
Matt Buckley50c44062022-01-17 20:48:10 +0000864 // Only start if possible to run and both threadids and duration are defined
Matt Buckley06f299a2021-09-24 19:43:51 +0000865 if (usePowerHintSession() && !oldPowerHintSessionThreadIds.empty()) {
Matt Buckley57274052022-08-12 21:54:23 +0000866 mPowerHintSessionRunning = mHalWrapper->startPowerHintSession();
Matt Buckley06f299a2021-09-24 19:43:51 +0000867 }
868 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800869 }
870
Dan Stoza9c051c02020-02-28 10:19:07 -0800871 // If we make it to this point and still don't have a HAL, it's unlikely we
872 // will, so stop trying
Matt Buckley57274052022-08-12 21:54:23 +0000873 if (mHalWrapper == nullptr) {
874 mHasHal = false;
Dan Stoza9c051c02020-02-28 10:19:07 -0800875 }
876
Matt Buckley57274052022-08-12 21:54:23 +0000877 return mHalWrapper.get();
Michael Wright1509a232018-06-21 02:50:34 +0100878}
879
880} // namespace impl
881} // namespace Hwc2
882} // namespace android