blob: cb2c8c53ef18f11aee63d1ac1ea574334b20fcd3 [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 Buckley06f299a2021-09-24 19:43:51 +000060using android::hardware::power::WorkDuration;
61
Michael Wright1509a232018-06-21 02:50:34 +010062PowerAdvisor::~PowerAdvisor() = default;
63
Dan Stoza030fbc12020-02-19 15:32:01 -080064namespace {
Alec Mouri29382ad2022-05-11 18:38:38 +000065std::chrono::milliseconds getUpdateTimeout() {
Dan Stoza030fbc12020-02-19 15:32:01 -080066 // Default to a timeout of 80ms if nothing else is specified
Alec Mouri29382ad2022-05-11 18:38:38 +000067 static std::chrono::milliseconds timeout =
68 std::chrono::milliseconds(sysprop::display_update_imminent_timeout_ms(80));
Dan Stoza030fbc12020-02-19 15:32:01 -080069 return timeout;
70}
71
Ady Abrahamabce1652022-02-24 10:51:19 -080072void traceExpensiveRendering(bool enabled) {
73 if (enabled) {
74 ATRACE_ASYNC_BEGIN("ExpensiveRendering", 0);
75 } else {
76 ATRACE_ASYNC_END("ExpensiveRendering", 0);
77 }
78}
79
Dan Stoza030fbc12020-02-19 15:32:01 -080080} // namespace
81
Alec Mouric059dcf2022-05-05 23:40:07 +000082PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger) : mFlinger(flinger) {
Alec Mouri29382ad2022-05-11 18:38:38 +000083 if (getUpdateTimeout() > 0ms) {
84 mScreenUpdateTimer.emplace("UpdateImminentTimer", getUpdateTimeout(),
Alec Mouric059dcf2022-05-05 23:40:07 +000085 /* resetCallback */ nullptr,
86 /* timeoutCallback */
87 [this] {
Alec Mouri29382ad2022-05-11 18:38:38 +000088 while (true) {
89 auto timeSinceLastUpdate = std::chrono::nanoseconds(
90 systemTime() - mLastScreenUpdatedTime.load());
91 if (timeSinceLastUpdate >= getUpdateTimeout()) {
92 break;
93 }
Alec Mouric059dcf2022-05-05 23:40:07 +000094 // We may try to disable expensive rendering and allow
95 // for sending DISPLAY_UPDATE_IMMINENT hints too early if
96 // we idled very shortly after updating the screen, so
97 // make sure we wait enough time.
Alec Mouri29382ad2022-05-11 18:38:38 +000098 std::this_thread::sleep_for(getUpdateTimeout() -
99 timeSinceLastUpdate);
Alec Mouric059dcf2022-05-05 23:40:07 +0000100 }
101 mSendUpdateImminent.store(true);
102 mFlinger.disableExpensiveRendering();
103 });
104 }
105}
Alec Mouridea1ac52021-06-23 18:12:18 -0700106
107void PowerAdvisor::init() {
108 // Defer starting the screen update timer until SurfaceFlinger finishes construction.
Alec Mouric059dcf2022-05-05 23:40:07 +0000109 if (mScreenUpdateTimer) {
110 mScreenUpdateTimer->start();
Dan Stoza030fbc12020-02-19 15:32:01 -0800111 }
112}
Michael Wright1509a232018-06-21 02:50:34 +0100113
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700114void PowerAdvisor::onBootFinished() {
115 mBootFinished.store(true);
116}
117
Peiyong Lin74ca2f42019-01-14 19:36:57 -0800118void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
Michael Wright1509a232018-06-21 02:50:34 +0100119 if (expected) {
120 mExpensiveDisplays.insert(displayId);
121 } else {
122 mExpensiveDisplays.erase(displayId);
123 }
124
Michael Wright1509a232018-06-21 02:50:34 +0100125 const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
126 if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
Dan Stoza20950002020-06-18 14:56:58 -0700127 std::lock_guard lock(mPowerHalMutex);
Dan Stoza030fbc12020-02-19 15:32:01 -0800128 HalWrapper* const halWrapper = getPowerHal();
129 if (halWrapper == nullptr) {
Peiyong Lin81934972018-07-02 11:00:54 -0700130 return;
131 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800132
133 if (!halWrapper->setExpensiveRendering(expectsExpensiveRendering)) {
134 // The HAL has become unavailable; attempt to reconnect later
Michael Wright1509a232018-06-21 02:50:34 +0100135 mReconnectPowerHal = true;
136 return;
137 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800138
Michael Wright1509a232018-06-21 02:50:34 +0100139 mNotifiedExpensiveRendering = expectsExpensiveRendering;
140 }
141}
142
Dan Stoza030fbc12020-02-19 15:32:01 -0800143void PowerAdvisor::notifyDisplayUpdateImminent() {
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700144 // Only start sending this notification once the system has booted so we don't introduce an
145 // early-boot dependency on Power HAL
146 if (!mBootFinished.load()) {
147 return;
148 }
149
Alec Mouric059dcf2022-05-05 23:40:07 +0000150 if (mSendUpdateImminent.exchange(false)) {
Dan Stoza20950002020-06-18 14:56:58 -0700151 std::lock_guard lock(mPowerHalMutex);
Dan Stoza030fbc12020-02-19 15:32:01 -0800152 HalWrapper* const halWrapper = getPowerHal();
153 if (halWrapper == nullptr) {
154 return;
155 }
156
157 if (!halWrapper->notifyDisplayUpdateImminent()) {
158 // The HAL has become unavailable; attempt to reconnect later
159 mReconnectPowerHal = true;
160 return;
161 }
Alec Mouric059dcf2022-05-05 23:40:07 +0000162
163 if (mScreenUpdateTimer) {
164 mScreenUpdateTimer->reset();
165 } else {
166 // If we don't have a screen update timer, then we don't throttle power hal calls so
167 // flip this bit back to allow for calling into power hal again.
168 mSendUpdateImminent.store(true);
169 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800170 }
171
Alec Mouric059dcf2022-05-05 23:40:07 +0000172 if (mScreenUpdateTimer) {
173 mLastScreenUpdatedTime.store(systemTime());
Dan Stoza030fbc12020-02-19 15:32:01 -0800174 }
175}
176
Matt Buckley06f299a2021-09-24 19:43:51 +0000177// checks both if it supports and if it's enabled
178bool PowerAdvisor::usePowerHintSession() {
179 // uses cached value since the underlying support and flag are unlikely to change at runtime
Matt Buckley06f299a2021-09-24 19:43:51 +0000180 return mPowerHintEnabled.value_or(false) && supportsPowerHintSession();
181}
182
183bool PowerAdvisor::supportsPowerHintSession() {
184 // cache to avoid needing lock every time
185 if (!mSupportsPowerHint.has_value()) {
186 std::lock_guard lock(mPowerHalMutex);
187 HalWrapper* const halWrapper = getPowerHal();
Shao-Chuan Lee65a2c192022-07-27 09:53:41 +0900188 mSupportsPowerHint = halWrapper && halWrapper->supportsPowerHintSession();
Matt Buckley06f299a2021-09-24 19:43:51 +0000189 }
190 return *mSupportsPowerHint;
191}
192
193bool PowerAdvisor::isPowerHintSessionRunning() {
194 return mPowerHintSessionRunning;
195}
196
Matt Buckley2fa85012022-08-30 22:38:45 +0000197void PowerAdvisor::setTargetWorkDuration(Duration targetDuration) {
Matt Buckleyef51fba2021-10-12 19:30:12 +0000198 if (!usePowerHintSession()) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000199 ALOGV("Power hint session target duration cannot be set, skipping");
200 return;
201 }
202 {
203 std::lock_guard lock(mPowerHalMutex);
204 HalWrapper* const halWrapper = getPowerHal();
205 if (halWrapper != nullptr) {
Matt Buckley50c44062022-01-17 20:48:10 +0000206 halWrapper->setTargetWorkDuration(targetDuration);
Matt Buckley06f299a2021-09-24 19:43:51 +0000207 }
208 }
209}
210
Matt Buckley50c44062022-01-17 20:48:10 +0000211void PowerAdvisor::sendActualWorkDuration() {
Matt Buckley06f299a2021-09-24 19:43:51 +0000212 if (!mBootFinished || !usePowerHintSession()) {
213 ALOGV("Actual work duration power hint cannot be sent, skipping");
214 return;
215 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000216 const std::optional<Duration> actualDuration = estimateWorkDuration(false);
Matt Buckley50c44062022-01-17 20:48:10 +0000217 if (actualDuration.has_value()) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000218 std::lock_guard lock(mPowerHalMutex);
219 HalWrapper* const halWrapper = getPowerHal();
220 if (halWrapper != nullptr) {
Matt Buckley2fa85012022-08-30 22:38:45 +0000221 halWrapper->sendActualWorkDuration(*actualDuration + kTargetSafetyMargin,
222 TimePoint::now());
Matt Buckley06f299a2021-09-24 19:43:51 +0000223 }
224 }
225}
226
Matt Buckley50c44062022-01-17 20:48:10 +0000227void PowerAdvisor::sendPredictedWorkDuration() {
228 if (!mBootFinished || !usePowerHintSession()) {
229 ALOGV("Actual work duration power hint cannot be sent, skipping");
230 return;
231 }
232
Matt Buckley2fa85012022-08-30 22:38:45 +0000233 const std::optional<Duration> predictedDuration = estimateWorkDuration(true);
Matt Buckley50c44062022-01-17 20:48:10 +0000234
235 if (predictedDuration.has_value()) {
236 std::lock_guard lock(mPowerHalMutex);
237 HalWrapper* const halWrapper = getPowerHal();
238 if (halWrapper != nullptr) {
Matt Buckley2fa85012022-08-30 22:38:45 +0000239 halWrapper->sendActualWorkDuration(*predictedDuration + kTargetSafetyMargin,
240 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
602 bool notifyDisplayUpdateImminent() override {
603 // 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
678bool AidlPowerHalWrapper::notifyDisplayUpdateImminent() {
679 ALOGV("AIDL notifyDisplayUpdateImminent");
680 if (!mHasDisplayUpdateImminent) {
681 ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
682 return true;
683 }
684
685 auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
686 return ret.isOk();
687}
688
Matt Buckley50c44062022-01-17 20:48:10 +0000689// Only version 2+ of the aidl supports power hint sessions, hidl has no support
Xiang Wange12b4fa2022-03-25 23:48:40 +0000690bool AidlPowerHalWrapper::supportsPowerHintSession() {
691 return mSupportsPowerHint;
692}
693
694bool AidlPowerHalWrapper::checkPowerHintSessionSupported() {
695 int64_t unused;
696 // Try to get preferred rate to determine if hint sessions are supported
697 // We check for isOk not EX_UNSUPPORTED_OPERATION to lump together errors
698 return mPowerHal->getHintSessionPreferredRate(&unused).isOk();
699}
700
701bool AidlPowerHalWrapper::isPowerHintSessionRunning() {
702 return mPowerHintSession != nullptr;
703}
704
705void AidlPowerHalWrapper::closePowerHintSession() {
706 if (mPowerHintSession != nullptr) {
707 mPowerHintSession->close();
708 mPowerHintSession = nullptr;
709 }
710}
711
712void AidlPowerHalWrapper::restartPowerHintSession() {
713 closePowerHintSession();
714 startPowerHintSession();
715}
716
717void AidlPowerHalWrapper::setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) {
718 if (threadIds != mPowerHintThreadIds) {
719 mPowerHintThreadIds = threadIds;
720 if (isPowerHintSessionRunning()) {
721 restartPowerHintSession();
722 }
723 }
724}
725
726bool AidlPowerHalWrapper::startPowerHintSession() {
727 if (mPowerHintSession != nullptr || mPowerHintThreadIds.empty()) {
728 ALOGV("Cannot start power hint session, skipping");
729 return false;
730 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000731 auto ret = mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
732 mPowerHintThreadIds, mTargetDuration.ns(),
733 &mPowerHintSession);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000734 if (!ret.isOk()) {
735 ALOGW("Failed to start power hint session with error: %s",
736 ret.exceptionToString(ret.exceptionCode()).c_str());
737 } else {
738 mLastTargetDurationSent = mTargetDuration;
739 }
740 return isPowerHintSessionRunning();
741}
742
Matt Buckley2fa85012022-08-30 22:38:45 +0000743void AidlPowerHalWrapper::setTargetWorkDuration(Duration targetDuration) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000744 ATRACE_CALL();
Matt Buckley50c44062022-01-17 20:48:10 +0000745 mTargetDuration = targetDuration;
Matt Buckley2fa85012022-08-30 22:38:45 +0000746 if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration.ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000747 if (isPowerHintSessionRunning() && (targetDuration != mLastTargetDurationSent)) {
Matt Buckley2fa85012022-08-30 22:38:45 +0000748 ALOGV("Sending target time: %" PRId64 "ns", targetDuration.ns());
Matt Buckley50c44062022-01-17 20:48:10 +0000749 mLastTargetDurationSent = targetDuration;
Matt Buckley2fa85012022-08-30 22:38:45 +0000750 auto ret = mPowerHintSession->updateTargetWorkDuration(targetDuration.ns());
Xiang Wange12b4fa2022-03-25 23:48:40 +0000751 if (!ret.isOk()) {
752 ALOGW("Failed to set power hint target work duration with error: %s",
753 ret.exceptionMessage().c_str());
754 mShouldReconnectHal = true;
755 }
756 }
757}
758
Matt Buckley2fa85012022-08-30 22:38:45 +0000759void AidlPowerHalWrapper::sendActualWorkDuration(Duration actualDuration, TimePoint timestamp) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000760 ATRACE_CALL();
Matt Buckley2fa85012022-08-30 22:38:45 +0000761 if (actualDuration < 0ns || !isPowerHintSessionRunning()) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000762 ALOGV("Failed to send actual work duration, skipping");
763 return;
764 }
Matt Buckley2fa85012022-08-30 22:38:45 +0000765 mActualDuration = actualDuration;
Xiang Wang0aba49e2022-04-06 16:13:59 +0000766 WorkDuration duration;
Matt Buckley2fa85012022-08-30 22:38:45 +0000767 duration.durationNanos = actualDuration.ns();
768 duration.timeStampNanos = timestamp.ns();
Xiang Wange12b4fa2022-03-25 23:48:40 +0000769 mPowerHintQueue.push_back(duration);
770
Xiang Wange12b4fa2022-03-25 23:48:40 +0000771 if (sTraceHintSessionData) {
Matt Buckley2fa85012022-08-30 22:38:45 +0000772 ATRACE_INT64("Measured duration", actualDuration.ns());
773 ATRACE_INT64("Target error term", Duration{actualDuration - mTargetDuration}.ns());
Xiang Wang0aba49e2022-04-06 16:13:59 +0000774
Matt Buckley2fa85012022-08-30 22:38:45 +0000775 ATRACE_INT64("Reported duration", actualDuration.ns());
776 ATRACE_INT64("Reported target", mLastTargetDurationSent.ns());
777 ATRACE_INT64("Reported target error term",
778 Duration{actualDuration - mLastTargetDurationSent}.ns());
Xiang Wange12b4fa2022-03-25 23:48:40 +0000779 }
780
Xiang Wang0aba49e2022-04-06 16:13:59 +0000781 ALOGV("Sending actual work duration of: %" PRId64 " on reported target: %" PRId64
Xiang Wange12b4fa2022-03-25 23:48:40 +0000782 " with error: %" PRId64,
Matt Buckley2fa85012022-08-30 22:38:45 +0000783 actualDuration.ns(), mLastTargetDurationSent.ns(),
784 Duration{actualDuration - mLastTargetDurationSent}.ns());
Xiang Wange12b4fa2022-03-25 23:48:40 +0000785
Matt Buckley44e612e2022-08-30 22:02:37 +0000786 auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue);
787 if (!ret.isOk()) {
788 ALOGW("Failed to report actual work durations with error: %s",
789 ret.exceptionMessage().c_str());
790 mShouldReconnectHal = true;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000791 }
Matt Buckley44e612e2022-08-30 22:02:37 +0000792 mPowerHintQueue.clear();
Xiang Wange12b4fa2022-03-25 23:48:40 +0000793}
794
795bool AidlPowerHalWrapper::shouldReconnectHAL() {
796 return mShouldReconnectHal;
797}
798
799std::vector<int32_t> AidlPowerHalWrapper::getPowerHintSessionThreadIds() {
800 return mPowerHintThreadIds;
801}
802
Matt Buckley2fa85012022-08-30 22:38:45 +0000803std::optional<Duration> AidlPowerHalWrapper::getTargetWorkDuration() {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000804 return mTargetDuration;
805}
806
Matt Buckleyef51fba2021-10-12 19:30:12 +0000807const bool AidlPowerHalWrapper::sTraceHintSessionData =
808 base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
809
Dan Stoza030fbc12020-02-19 15:32:01 -0800810PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
Matt Buckley57274052022-08-12 21:54:23 +0000811 if (!mHasHal) {
Dan Stoza9c051c02020-02-28 10:19:07 -0800812 return nullptr;
813 }
814
Matt Buckley50c44062022-01-17 20:48:10 +0000815 // Grab old hint session values before we destroy any existing wrapper
Matt Buckley06f299a2021-09-24 19:43:51 +0000816 std::vector<int32_t> oldPowerHintSessionThreadIds;
Matt Buckley2fa85012022-08-30 22:38:45 +0000817 std::optional<Duration> oldTargetWorkDuration;
Matt Buckley06f299a2021-09-24 19:43:51 +0000818
Matt Buckley57274052022-08-12 21:54:23 +0000819 if (mHalWrapper != nullptr) {
820 oldPowerHintSessionThreadIds = mHalWrapper->getPowerHintSessionThreadIds();
821 oldTargetWorkDuration = mHalWrapper->getTargetWorkDuration();
Matt Buckley06f299a2021-09-24 19:43:51 +0000822 }
823
Dan Stoza9c051c02020-02-28 10:19:07 -0800824 // If we used to have a HAL, but it stopped responding, attempt to reconnect
Michael Wright1509a232018-06-21 02:50:34 +0100825 if (mReconnectPowerHal) {
Matt Buckley57274052022-08-12 21:54:23 +0000826 mHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100827 mReconnectPowerHal = false;
828 }
829
Matt Buckley57274052022-08-12 21:54:23 +0000830 if (mHalWrapper != nullptr) {
831 auto wrapper = mHalWrapper.get();
Matt Buckley50c44062022-01-17 20:48:10 +0000832 // If the wrapper is fine, return it, but if it indicates a reconnect, remake it
Matt Buckley06f299a2021-09-24 19:43:51 +0000833 if (!wrapper->shouldReconnectHAL()) {
834 return wrapper;
835 }
Xiang Wang65a2e6f2022-04-18 21:19:17 +0000836 ALOGD("Reconnecting Power HAL");
Matt Buckley57274052022-08-12 21:54:23 +0000837 mHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100838 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800839
Matt Buckley50c44062022-01-17 20:48:10 +0000840 // At this point, we know for sure there is no running session
Matt Buckley06f299a2021-09-24 19:43:51 +0000841 mPowerHintSessionRunning = false;
842
Dan Stoza030fbc12020-02-19 15:32:01 -0800843 // First attempt to connect to the AIDL Power HAL
Matt Buckley57274052022-08-12 21:54:23 +0000844 mHalWrapper = AidlPowerHalWrapper::connect();
Dan Stoza030fbc12020-02-19 15:32:01 -0800845
846 // If that didn't succeed, attempt to connect to the HIDL Power HAL
Matt Buckley57274052022-08-12 21:54:23 +0000847 if (mHalWrapper == nullptr) {
848 mHalWrapper = HidlPowerHalWrapper::connect();
Xiang Wang65a2e6f2022-04-18 21:19:17 +0000849 } else {
850 ALOGD("Successfully connecting AIDL Power HAL");
Matt Buckley50c44062022-01-17 20:48:10 +0000851 // If AIDL, pass on any existing hint session values
Matt Buckley57274052022-08-12 21:54:23 +0000852 mHalWrapper->setPowerHintSessionThreadIds(oldPowerHintSessionThreadIds);
Matt Buckley50c44062022-01-17 20:48:10 +0000853 // Only set duration and start if duration is defined
Matt Buckley06f299a2021-09-24 19:43:51 +0000854 if (oldTargetWorkDuration.has_value()) {
Matt Buckley57274052022-08-12 21:54:23 +0000855 mHalWrapper->setTargetWorkDuration(*oldTargetWorkDuration);
Matt Buckley50c44062022-01-17 20:48:10 +0000856 // Only start if possible to run and both threadids and duration are defined
Matt Buckley06f299a2021-09-24 19:43:51 +0000857 if (usePowerHintSession() && !oldPowerHintSessionThreadIds.empty()) {
Matt Buckley57274052022-08-12 21:54:23 +0000858 mPowerHintSessionRunning = mHalWrapper->startPowerHintSession();
Matt Buckley06f299a2021-09-24 19:43:51 +0000859 }
860 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800861 }
862
Dan Stoza9c051c02020-02-28 10:19:07 -0800863 // If we make it to this point and still don't have a HAL, it's unlikely we
864 // will, so stop trying
Matt Buckley57274052022-08-12 21:54:23 +0000865 if (mHalWrapper == nullptr) {
866 mHasHal = false;
Dan Stoza9c051c02020-02-28 10:19:07 -0800867 }
868
Matt Buckley57274052022-08-12 21:54:23 +0000869 return mHalWrapper.get();
Michael Wright1509a232018-06-21 02:50:34 +0100870}
871
872} // namespace impl
873} // namespace Hwc2
874} // namespace android