• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 #undef LOG_TAG
18 #define LOG_TAG "Scheduler"
19 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
20 
21 #include "Scheduler.h"
22 
23 #include <android-base/properties.h>
24 #include <android-base/stringprintf.h>
25 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
26 #include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
27 #include <configstore/Utils.h>
28 #include <ftl/fake_guard.h>
29 #include <gui/WindowInfo.h>
30 #include <system/window.h>
31 #include <ui/DisplayStatInfo.h>
32 #include <utils/Timers.h>
33 #include <utils/Trace.h>
34 
35 #include <FrameTimeline/FrameTimeline.h>
36 #include <algorithm>
37 #include <cinttypes>
38 #include <cstdint>
39 #include <functional>
40 #include <memory>
41 #include <numeric>
42 
43 #include "../Layer.h"
44 #include "DispSyncSource.h"
45 #include "EventThread.h"
46 #include "FrameRateOverrideMappings.h"
47 #include "InjectVSyncSource.h"
48 #include "OneShotTimer.h"
49 #include "SurfaceFlingerProperties.h"
50 #include "VSyncPredictor.h"
51 #include "VSyncReactor.h"
52 
53 #define RETURN_IF_INVALID_HANDLE(handle, ...)                        \
54     do {                                                             \
55         if (mConnections.count(handle) == 0) {                       \
56             ALOGE("Invalid connection handle %" PRIuPTR, handle.id); \
57             return __VA_ARGS__;                                      \
58         }                                                            \
59     } while (false)
60 
61 namespace android::scheduler {
62 
Scheduler(ICompositor & compositor,ISchedulerCallback & callback,FeatureFlags features)63 Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features)
64       : impl::MessageQueue(compositor), mFeatures(features), mSchedulerCallback(callback) {}
65 
~Scheduler()66 Scheduler::~Scheduler() {
67     // Stop timers and wait for their threads to exit.
68     mDisplayPowerTimer.reset();
69     mTouchTimer.reset();
70 
71     // Stop idle timer and clear callbacks, as the RefreshRateConfigs may outlive the Scheduler.
72     setRefreshRateConfigs(nullptr);
73 }
74 
startTimers()75 void Scheduler::startTimers() {
76     using namespace sysprop;
77     using namespace std::string_literals;
78 
79     if (const int64_t millis = set_touch_timer_ms(0); millis > 0) {
80         // Touch events are coming to SF every 100ms, so the timer needs to be higher than that
81         mTouchTimer.emplace(
82                 "TouchTimer", std::chrono::milliseconds(millis),
83                 [this] { touchTimerCallback(TimerState::Reset); },
84                 [this] { touchTimerCallback(TimerState::Expired); });
85         mTouchTimer->start();
86     }
87 
88     if (const int64_t millis = set_display_power_timer_ms(0); millis > 0) {
89         mDisplayPowerTimer.emplace(
90                 "DisplayPowerTimer", std::chrono::milliseconds(millis),
91                 [this] { displayPowerTimerCallback(TimerState::Reset); },
92                 [this] { displayPowerTimerCallback(TimerState::Expired); });
93         mDisplayPowerTimer->start();
94     }
95 }
96 
setRefreshRateConfigs(std::shared_ptr<RefreshRateConfigs> configs)97 void Scheduler::setRefreshRateConfigs(std::shared_ptr<RefreshRateConfigs> configs) {
98     // The current RefreshRateConfigs instance may outlive this call, so unbind its idle timer.
99     {
100         // mRefreshRateConfigsLock is not locked here to avoid the deadlock
101         // as the callback can attempt to acquire the lock before stopIdleTimer can finish
102         // the execution. It's safe to FakeGuard as main thread is the only thread that
103         // writes to the mRefreshRateConfigs.
104         ftl::FakeGuard guard(mRefreshRateConfigsLock);
105         if (mRefreshRateConfigs) {
106             mRefreshRateConfigs->stopIdleTimer();
107             mRefreshRateConfigs->clearIdleTimerCallbacks();
108         }
109     }
110     {
111         // Clear state that depends on the current instance.
112         std::scoped_lock lock(mPolicyLock);
113         mPolicy = {};
114     }
115 
116     std::scoped_lock lock(mRefreshRateConfigsLock);
117     mRefreshRateConfigs = std::move(configs);
118     if (!mRefreshRateConfigs) return;
119 
120     mRefreshRateConfigs->setIdleTimerCallbacks(
121             {.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); },
122                           .onExpired = [this] { idleTimerCallback(TimerState::Expired); }},
123              .kernel = {.onReset = [this] { kernelIdleTimerCallback(TimerState::Reset); },
124                         .onExpired = [this] { kernelIdleTimerCallback(TimerState::Expired); }}});
125 
126     mRefreshRateConfigs->startIdleTimer();
127 }
128 
run()129 void Scheduler::run() {
130     while (true) {
131         waitMessage();
132     }
133 }
134 
createVsyncSchedule(FeatureFlags features)135 void Scheduler::createVsyncSchedule(FeatureFlags features) {
136     mVsyncSchedule.emplace(features);
137 }
138 
makePrimaryDispSyncSource(const char * name,std::chrono::nanoseconds workDuration,std::chrono::nanoseconds readyDuration,bool traceVsync)139 std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource(
140         const char* name, std::chrono::nanoseconds workDuration,
141         std::chrono::nanoseconds readyDuration, bool traceVsync) {
142     return std::make_unique<scheduler::DispSyncSource>(mVsyncSchedule->getDispatch(),
143                                                        mVsyncSchedule->getTracker(), workDuration,
144                                                        readyDuration, traceVsync, name);
145 }
146 
getFrameRateOverride(uid_t uid) const147 std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
148     const auto refreshRateConfigs = holdRefreshRateConfigs();
149     const bool supportsFrameRateOverrideByContent =
150             refreshRateConfigs->supportsFrameRateOverrideByContent();
151     return mFrameRateOverrideMappings
152             .getFrameRateOverrideForUid(uid, supportsFrameRateOverrideByContent);
153 }
154 
isVsyncValid(nsecs_t expectedVsyncTimestamp,uid_t uid) const155 bool Scheduler::isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const {
156     const auto frameRate = getFrameRateOverride(uid);
157     if (!frameRate.has_value()) {
158         return true;
159     }
160 
161     return mVsyncSchedule->getTracker().isVSyncInPhase(expectedVsyncTimestamp, *frameRate);
162 }
163 
makeThrottleVsyncCallback() const164 impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() const {
165     std::scoped_lock lock(mRefreshRateConfigsLock);
166 
167     return [this](nsecs_t expectedVsyncTimestamp, uid_t uid) {
168         return !isVsyncValid(expectedVsyncTimestamp, uid);
169     };
170 }
171 
makeGetVsyncPeriodFunction() const172 impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const {
173     return [this](uid_t uid) {
174         const Fps refreshRate = holdRefreshRateConfigs()->getActiveMode()->getFps();
175         const auto currentPeriod =
176                 mVsyncSchedule->getTracker().currentPeriod() ?: refreshRate.getPeriodNsecs();
177 
178         const auto frameRate = getFrameRateOverride(uid);
179         if (!frameRate.has_value()) {
180             return currentPeriod;
181         }
182 
183         const auto divisor = RefreshRateConfigs::getFrameRateDivisor(refreshRate, *frameRate);
184         if (divisor <= 1) {
185             return currentPeriod;
186         }
187         return currentPeriod * divisor;
188     };
189 }
190 
createConnection(const char * connectionName,frametimeline::TokenManager * tokenManager,std::chrono::nanoseconds workDuration,std::chrono::nanoseconds readyDuration,impl::EventThread::InterceptVSyncsCallback interceptCallback)191 ConnectionHandle Scheduler::createConnection(
192         const char* connectionName, frametimeline::TokenManager* tokenManager,
193         std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
194         impl::EventThread::InterceptVSyncsCallback interceptCallback) {
195     auto vsyncSource = makePrimaryDispSyncSource(connectionName, workDuration, readyDuration);
196     auto throttleVsync = makeThrottleVsyncCallback();
197     auto getVsyncPeriod = makeGetVsyncPeriodFunction();
198     auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource), tokenManager,
199                                                            std::move(interceptCallback),
200                                                            std::move(throttleVsync),
201                                                            std::move(getVsyncPeriod));
202     return createConnection(std::move(eventThread));
203 }
204 
createConnection(std::unique_ptr<EventThread> eventThread)205 ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) {
206     const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++};
207     ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id);
208 
209     auto connection = createConnectionInternal(eventThread.get());
210 
211     std::lock_guard<std::mutex> lock(mConnectionsLock);
212     mConnections.emplace(handle, Connection{connection, std::move(eventThread)});
213     return handle;
214 }
215 
createConnectionInternal(EventThread * eventThread,ISurfaceComposer::EventRegistrationFlags eventRegistration)216 sp<EventThreadConnection> Scheduler::createConnectionInternal(
217         EventThread* eventThread, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
218     return eventThread->createEventConnection([&] { resync(); }, eventRegistration);
219 }
220 
createDisplayEventConnection(ConnectionHandle handle,ISurfaceComposer::EventRegistrationFlags eventRegistration)221 sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
222         ConnectionHandle handle, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
223     std::lock_guard<std::mutex> lock(mConnectionsLock);
224     RETURN_IF_INVALID_HANDLE(handle, nullptr);
225     return createConnectionInternal(mConnections[handle].thread.get(), eventRegistration);
226 }
227 
getEventConnection(ConnectionHandle handle)228 sp<EventThreadConnection> Scheduler::getEventConnection(ConnectionHandle handle) {
229     std::lock_guard<std::mutex> lock(mConnectionsLock);
230     RETURN_IF_INVALID_HANDLE(handle, nullptr);
231     return mConnections[handle].connection;
232 }
233 
onHotplugReceived(ConnectionHandle handle,PhysicalDisplayId displayId,bool connected)234 void Scheduler::onHotplugReceived(ConnectionHandle handle, PhysicalDisplayId displayId,
235                                   bool connected) {
236     android::EventThread* thread;
237     {
238         std::lock_guard<std::mutex> lock(mConnectionsLock);
239         RETURN_IF_INVALID_HANDLE(handle);
240         thread = mConnections[handle].thread.get();
241     }
242 
243     thread->onHotplugReceived(displayId, connected);
244 }
245 
onScreenAcquired(ConnectionHandle handle)246 void Scheduler::onScreenAcquired(ConnectionHandle handle) {
247     android::EventThread* thread;
248     {
249         std::lock_guard<std::mutex> lock(mConnectionsLock);
250         RETURN_IF_INVALID_HANDLE(handle);
251         thread = mConnections[handle].thread.get();
252     }
253     thread->onScreenAcquired();
254     mScreenAcquired = true;
255 }
256 
onScreenReleased(ConnectionHandle handle)257 void Scheduler::onScreenReleased(ConnectionHandle handle) {
258     android::EventThread* thread;
259     {
260         std::lock_guard<std::mutex> lock(mConnectionsLock);
261         RETURN_IF_INVALID_HANDLE(handle);
262         thread = mConnections[handle].thread.get();
263     }
264     thread->onScreenReleased();
265     mScreenAcquired = false;
266 }
267 
onFrameRateOverridesChanged(ConnectionHandle handle,PhysicalDisplayId displayId)268 void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) {
269     const auto refreshRateConfigs = holdRefreshRateConfigs();
270     const bool supportsFrameRateOverrideByContent =
271             refreshRateConfigs->supportsFrameRateOverrideByContent();
272 
273     std::vector<FrameRateOverride> overrides =
274             mFrameRateOverrideMappings.getAllFrameRateOverrides(supportsFrameRateOverrideByContent);
275 
276     android::EventThread* thread;
277     {
278         std::lock_guard lock(mConnectionsLock);
279         RETURN_IF_INVALID_HANDLE(handle);
280         thread = mConnections[handle].thread.get();
281     }
282     thread->onFrameRateOverridesChanged(displayId, std::move(overrides));
283 }
284 
onPrimaryDisplayModeChanged(ConnectionHandle handle,DisplayModePtr mode)285 void Scheduler::onPrimaryDisplayModeChanged(ConnectionHandle handle, DisplayModePtr mode) {
286     {
287         std::lock_guard<std::mutex> lock(mPolicyLock);
288         // Cache the last reported modes for primary display.
289         mPolicy.cachedModeChangedParams = {handle, mode};
290 
291         // Invalidate content based refresh rate selection so it could be calculated
292         // again for the new refresh rate.
293         mPolicy.contentRequirements.clear();
294     }
295     onNonPrimaryDisplayModeChanged(handle, mode);
296 }
297 
dispatchCachedReportedMode()298 void Scheduler::dispatchCachedReportedMode() {
299     // Check optional fields first.
300     if (!mPolicy.mode) {
301         ALOGW("No mode ID found, not dispatching cached mode.");
302         return;
303     }
304     if (!mPolicy.cachedModeChangedParams) {
305         ALOGW("No mode changed params found, not dispatching cached mode.");
306         return;
307     }
308 
309     // If the mode is not the current mode, this means that a
310     // mode change is in progress. In that case we shouldn't dispatch an event
311     // as it will be dispatched when the current mode changes.
312     if (std::scoped_lock lock(mRefreshRateConfigsLock);
313         mRefreshRateConfigs->getActiveMode() != mPolicy.mode) {
314         return;
315     }
316 
317     // If there is no change from cached mode, there is no need to dispatch an event
318     if (mPolicy.mode == mPolicy.cachedModeChangedParams->mode) {
319         return;
320     }
321 
322     mPolicy.cachedModeChangedParams->mode = mPolicy.mode;
323     onNonPrimaryDisplayModeChanged(mPolicy.cachedModeChangedParams->handle,
324                                    mPolicy.cachedModeChangedParams->mode);
325 }
326 
onNonPrimaryDisplayModeChanged(ConnectionHandle handle,DisplayModePtr mode)327 void Scheduler::onNonPrimaryDisplayModeChanged(ConnectionHandle handle, DisplayModePtr mode) {
328     android::EventThread* thread;
329     {
330         std::lock_guard<std::mutex> lock(mConnectionsLock);
331         RETURN_IF_INVALID_HANDLE(handle);
332         thread = mConnections[handle].thread.get();
333     }
334     thread->onModeChanged(mode);
335 }
336 
getEventThreadConnectionCount(ConnectionHandle handle)337 size_t Scheduler::getEventThreadConnectionCount(ConnectionHandle handle) {
338     std::lock_guard<std::mutex> lock(mConnectionsLock);
339     RETURN_IF_INVALID_HANDLE(handle, 0);
340     return mConnections[handle].thread->getEventThreadConnectionCount();
341 }
342 
dump(ConnectionHandle handle,std::string & result) const343 void Scheduler::dump(ConnectionHandle handle, std::string& result) const {
344     android::EventThread* thread;
345     {
346         std::lock_guard<std::mutex> lock(mConnectionsLock);
347         RETURN_IF_INVALID_HANDLE(handle);
348         thread = mConnections.at(handle).thread.get();
349     }
350     thread->dump(result);
351 }
352 
setDuration(ConnectionHandle handle,std::chrono::nanoseconds workDuration,std::chrono::nanoseconds readyDuration)353 void Scheduler::setDuration(ConnectionHandle handle, std::chrono::nanoseconds workDuration,
354                             std::chrono::nanoseconds readyDuration) {
355     android::EventThread* thread;
356     {
357         std::lock_guard<std::mutex> lock(mConnectionsLock);
358         RETURN_IF_INVALID_HANDLE(handle);
359         thread = mConnections[handle].thread.get();
360     }
361     thread->setDuration(workDuration, readyDuration);
362 }
363 
getDisplayStatInfo(nsecs_t now)364 DisplayStatInfo Scheduler::getDisplayStatInfo(nsecs_t now) {
365     const auto vsyncTime = mVsyncSchedule->getTracker().nextAnticipatedVSyncTimeFrom(now);
366     const auto vsyncPeriod = mVsyncSchedule->getTracker().currentPeriod();
367     return DisplayStatInfo{.vsyncTime = vsyncTime, .vsyncPeriod = vsyncPeriod};
368 }
369 
enableVSyncInjection(bool enable)370 ConnectionHandle Scheduler::enableVSyncInjection(bool enable) {
371     if (mInjectVSyncs == enable) {
372         return {};
373     }
374 
375     ALOGV("%s VSYNC injection", enable ? "Enabling" : "Disabling");
376 
377     if (!mInjectorConnectionHandle) {
378         auto vsyncSource = std::make_unique<InjectVSyncSource>();
379         mVSyncInjector = vsyncSource.get();
380 
381         auto eventThread =
382                 std::make_unique<impl::EventThread>(std::move(vsyncSource),
383                                                     /*tokenManager=*/nullptr,
384                                                     impl::EventThread::InterceptVSyncsCallback(),
385                                                     impl::EventThread::ThrottleVsyncCallback(),
386                                                     impl::EventThread::GetVsyncPeriodFunction());
387 
388         // EventThread does not dispatch VSYNC unless the display is connected and powered on.
389         eventThread->onHotplugReceived(PhysicalDisplayId::fromPort(0), true);
390         eventThread->onScreenAcquired();
391 
392         mInjectorConnectionHandle = createConnection(std::move(eventThread));
393     }
394 
395     mInjectVSyncs = enable;
396     return mInjectorConnectionHandle;
397 }
398 
injectVSync(nsecs_t when,nsecs_t expectedVSyncTime,nsecs_t deadlineTimestamp)399 bool Scheduler::injectVSync(nsecs_t when, nsecs_t expectedVSyncTime, nsecs_t deadlineTimestamp) {
400     if (!mInjectVSyncs || !mVSyncInjector) {
401         return false;
402     }
403 
404     mVSyncInjector->onInjectSyncEvent(when, expectedVSyncTime, deadlineTimestamp);
405     return true;
406 }
407 
enableHardwareVsync()408 void Scheduler::enableHardwareVsync() {
409     std::lock_guard<std::mutex> lock(mHWVsyncLock);
410     if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
411         mVsyncSchedule->getTracker().resetModel();
412         mSchedulerCallback.setVsyncEnabled(true);
413         mPrimaryHWVsyncEnabled = true;
414     }
415 }
416 
disableHardwareVsync(bool makeUnavailable)417 void Scheduler::disableHardwareVsync(bool makeUnavailable) {
418     std::lock_guard<std::mutex> lock(mHWVsyncLock);
419     if (mPrimaryHWVsyncEnabled) {
420         mSchedulerCallback.setVsyncEnabled(false);
421         mPrimaryHWVsyncEnabled = false;
422     }
423     if (makeUnavailable) {
424         mHWVsyncAvailable = false;
425     }
426 }
427 
resyncToHardwareVsync(bool makeAvailable,Fps refreshRate)428 void Scheduler::resyncToHardwareVsync(bool makeAvailable, Fps refreshRate) {
429     {
430         std::lock_guard<std::mutex> lock(mHWVsyncLock);
431         if (makeAvailable) {
432             mHWVsyncAvailable = makeAvailable;
433         } else if (!mHWVsyncAvailable) {
434             // Hardware vsync is not currently available, so abort the resync
435             // attempt for now
436             return;
437         }
438     }
439 
440     setVsyncPeriod(refreshRate.getPeriodNsecs());
441 }
442 
resync()443 void Scheduler::resync() {
444     static constexpr nsecs_t kIgnoreDelay = ms2ns(750);
445 
446     const nsecs_t now = systemTime();
447     const nsecs_t last = mLastResyncTime.exchange(now);
448 
449     if (now - last > kIgnoreDelay) {
450         const auto refreshRate = [&] {
451             std::scoped_lock lock(mRefreshRateConfigsLock);
452             return mRefreshRateConfigs->getActiveMode()->getFps();
453         }();
454         resyncToHardwareVsync(false, refreshRate);
455     }
456 }
457 
setVsyncPeriod(nsecs_t period)458 void Scheduler::setVsyncPeriod(nsecs_t period) {
459     if (period <= 0) return;
460 
461     std::lock_guard<std::mutex> lock(mHWVsyncLock);
462     mVsyncSchedule->getController().startPeriodTransition(period);
463 
464     if (!mPrimaryHWVsyncEnabled) {
465         mVsyncSchedule->getTracker().resetModel();
466         mSchedulerCallback.setVsyncEnabled(true);
467         mPrimaryHWVsyncEnabled = true;
468     }
469 }
470 
addResyncSample(nsecs_t timestamp,std::optional<nsecs_t> hwcVsyncPeriod,bool * periodFlushed)471 void Scheduler::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
472                                 bool* periodFlushed) {
473     bool needsHwVsync = false;
474     *periodFlushed = false;
475     { // Scope for the lock
476         std::lock_guard<std::mutex> lock(mHWVsyncLock);
477         if (mPrimaryHWVsyncEnabled) {
478             needsHwVsync =
479                     mVsyncSchedule->getController().addHwVsyncTimestamp(timestamp, hwcVsyncPeriod,
480                                                                         periodFlushed);
481         }
482     }
483 
484     if (needsHwVsync) {
485         enableHardwareVsync();
486     } else {
487         disableHardwareVsync(false);
488     }
489 }
490 
addPresentFence(std::shared_ptr<FenceTime> fence)491 void Scheduler::addPresentFence(std::shared_ptr<FenceTime> fence) {
492     if (mVsyncSchedule->getController().addPresentFence(std::move(fence))) {
493         enableHardwareVsync();
494     } else {
495         disableHardwareVsync(false);
496     }
497 }
498 
registerLayer(Layer * layer)499 void Scheduler::registerLayer(Layer* layer) {
500     using WindowType = gui::WindowInfo::Type;
501 
502     scheduler::LayerHistory::LayerVoteType voteType;
503 
504     if (!mFeatures.test(Feature::kContentDetection) ||
505         layer->getWindowType() == WindowType::STATUS_BAR) {
506         voteType = scheduler::LayerHistory::LayerVoteType::NoVote;
507     } else if (layer->getWindowType() == WindowType::WALLPAPER) {
508         // Running Wallpaper at Min is considered as part of content detection.
509         voteType = scheduler::LayerHistory::LayerVoteType::Min;
510     } else {
511         voteType = scheduler::LayerHistory::LayerVoteType::Heuristic;
512     }
513 
514     // If the content detection feature is off, we still keep the layer history,
515     // since we use it for other features (like Frame Rate API), so layers
516     // still need to be registered.
517     mLayerHistory.registerLayer(layer, voteType);
518 }
519 
deregisterLayer(Layer * layer)520 void Scheduler::deregisterLayer(Layer* layer) {
521     mLayerHistory.deregisterLayer(layer);
522 }
523 
recordLayerHistory(Layer * layer,nsecs_t presentTime,LayerHistory::LayerUpdateType updateType)524 void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime,
525                                    LayerHistory::LayerUpdateType updateType) {
526     {
527         std::scoped_lock lock(mRefreshRateConfigsLock);
528         if (!mRefreshRateConfigs->canSwitch()) return;
529     }
530 
531     mLayerHistory.record(layer, presentTime, systemTime(), updateType);
532 }
533 
setModeChangePending(bool pending)534 void Scheduler::setModeChangePending(bool pending) {
535     mLayerHistory.setModeChangePending(pending);
536 }
537 
chooseRefreshRateForContent()538 void Scheduler::chooseRefreshRateForContent() {
539     const auto configs = holdRefreshRateConfigs();
540     if (!configs->canSwitch()) return;
541 
542     ATRACE_CALL();
543 
544     LayerHistory::Summary summary = mLayerHistory.summarize(*configs, systemTime());
545     applyPolicy(&Policy::contentRequirements, std::move(summary));
546 }
547 
resetIdleTimer()548 void Scheduler::resetIdleTimer() {
549     std::scoped_lock lock(mRefreshRateConfigsLock);
550     mRefreshRateConfigs->resetIdleTimer(/*kernelOnly*/ false);
551 }
552 
onTouchHint()553 void Scheduler::onTouchHint() {
554     if (mTouchTimer) {
555         mTouchTimer->reset();
556 
557         std::scoped_lock lock(mRefreshRateConfigsLock);
558         mRefreshRateConfigs->resetIdleTimer(/*kernelOnly*/ true);
559     }
560 }
561 
setDisplayPowerMode(hal::PowerMode powerMode)562 void Scheduler::setDisplayPowerMode(hal::PowerMode powerMode) {
563     {
564         std::lock_guard<std::mutex> lock(mPolicyLock);
565         mPolicy.displayPowerMode = powerMode;
566     }
567     mVsyncSchedule->getController().setDisplayPowerMode(powerMode);
568 
569     if (mDisplayPowerTimer) {
570         mDisplayPowerTimer->reset();
571     }
572 
573     // Display Power event will boost the refresh rate to performance.
574     // Clear Layer History to get fresh FPS detection
575     mLayerHistory.clear();
576 }
577 
kernelIdleTimerCallback(TimerState state)578 void Scheduler::kernelIdleTimerCallback(TimerState state) {
579     ATRACE_INT("ExpiredKernelIdleTimer", static_cast<int>(state));
580 
581     // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate
582     // magic number
583     const Fps refreshRate = [&] {
584         std::scoped_lock lock(mRefreshRateConfigsLock);
585         return mRefreshRateConfigs->getActiveMode()->getFps();
586     }();
587 
588     constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER = 65_Hz;
589     using namespace fps_approx_ops;
590 
591     if (state == TimerState::Reset && refreshRate > FPS_THRESHOLD_FOR_KERNEL_TIMER) {
592         // If we're not in performance mode then the kernel timer shouldn't do
593         // anything, as the refresh rate during DPU power collapse will be the
594         // same.
595         resyncToHardwareVsync(true /* makeAvailable */, refreshRate);
596     } else if (state == TimerState::Expired && refreshRate <= FPS_THRESHOLD_FOR_KERNEL_TIMER) {
597         // Disable HW VSYNC if the timer expired, as we don't need it enabled if
598         // we're not pushing frames, and if we're in PERFORMANCE mode then we'll
599         // need to update the VsyncController model anyway.
600         disableHardwareVsync(false /* makeUnavailable */);
601     }
602 
603     mSchedulerCallback.kernelTimerChanged(state == TimerState::Expired);
604 }
605 
idleTimerCallback(TimerState state)606 void Scheduler::idleTimerCallback(TimerState state) {
607     applyPolicy(&Policy::idleTimer, state);
608     ATRACE_INT("ExpiredIdleTimer", static_cast<int>(state));
609 }
610 
touchTimerCallback(TimerState state)611 void Scheduler::touchTimerCallback(TimerState state) {
612     const TouchState touch = state == TimerState::Reset ? TouchState::Active : TouchState::Inactive;
613     // Touch event will boost the refresh rate to performance.
614     // Clear layer history to get fresh FPS detection.
615     // NOTE: Instead of checking all the layers, we should be checking the layer
616     // that is currently on top. b/142507166 will give us this capability.
617     if (applyPolicy(&Policy::touch, touch).touch) {
618         mLayerHistory.clear();
619     }
620     ATRACE_INT("TouchState", static_cast<int>(touch));
621 }
622 
displayPowerTimerCallback(TimerState state)623 void Scheduler::displayPowerTimerCallback(TimerState state) {
624     applyPolicy(&Policy::displayPowerTimer, state);
625     ATRACE_INT("ExpiredDisplayPowerTimer", static_cast<int>(state));
626 }
627 
dump(std::string & result) const628 void Scheduler::dump(std::string& result) const {
629     using base::StringAppendF;
630 
631     StringAppendF(&result, "+  Touch timer: %s\n",
632                   mTouchTimer ? mTouchTimer->dump().c_str() : "off");
633     StringAppendF(&result, "+  Content detection: %s %s\n\n",
634                   mFeatures.test(Feature::kContentDetection) ? "on" : "off",
635                   mLayerHistory.dump().c_str());
636 
637     mFrameRateOverrideMappings.dump(result);
638 
639     {
640         std::lock_guard lock(mHWVsyncLock);
641         StringAppendF(&result,
642                       "mScreenAcquired=%d mPrimaryHWVsyncEnabled=%d mHWVsyncAvailable=%d\n",
643                       mScreenAcquired.load(), mPrimaryHWVsyncEnabled, mHWVsyncAvailable);
644     }
645 }
646 
dumpVsync(std::string & out) const647 void Scheduler::dumpVsync(std::string& out) const {
648     mVsyncSchedule->dump(out);
649 }
650 
updateFrameRateOverrides(GlobalSignals consideredSignals,Fps displayRefreshRate)651 bool Scheduler::updateFrameRateOverrides(GlobalSignals consideredSignals, Fps displayRefreshRate) {
652     const auto refreshRateConfigs = holdRefreshRateConfigs();
653 
654     // we always update mFrameRateOverridesByContent here
655     // supportsFrameRateOverridesByContent will be checked
656     // when getting FrameRateOverrides from mFrameRateOverrideMappings
657     if (!consideredSignals.idle) {
658         const auto frameRateOverrides =
659                 refreshRateConfigs->getFrameRateOverrides(mPolicy.contentRequirements,
660                                                           displayRefreshRate, consideredSignals);
661         return mFrameRateOverrideMappings.updateFrameRateOverridesByContent(frameRateOverrides);
662     }
663     return false;
664 }
665 
666 template <typename S, typename T>
applyPolicy(S Policy::* statePtr,T && newState)667 auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals {
668     DisplayModePtr newMode;
669     GlobalSignals consideredSignals;
670 
671     bool refreshRateChanged = false;
672     bool frameRateOverridesChanged;
673 
674     const auto refreshRateConfigs = holdRefreshRateConfigs();
675     {
676         std::lock_guard<std::mutex> lock(mPolicyLock);
677 
678         auto& currentState = mPolicy.*statePtr;
679         if (currentState == newState) return {};
680         currentState = std::forward<T>(newState);
681 
682         std::tie(newMode, consideredSignals) = chooseDisplayMode();
683         frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newMode->getFps());
684 
685         if (mPolicy.mode == newMode) {
686             // We don't need to change the display mode, but we might need to send an event
687             // about a mode change, since it was suppressed if previously considered idle.
688             if (!consideredSignals.idle) {
689                 dispatchCachedReportedMode();
690             }
691         } else {
692             mPolicy.mode = newMode;
693             refreshRateChanged = true;
694         }
695     }
696     if (refreshRateChanged) {
697         mSchedulerCallback.requestDisplayMode(std::move(newMode),
698                                               consideredSignals.idle ? DisplayModeEvent::None
699                                                                      : DisplayModeEvent::Changed);
700     }
701     if (frameRateOverridesChanged) {
702         mSchedulerCallback.triggerOnFrameRateOverridesChanged();
703     }
704     return consideredSignals;
705 }
706 
chooseDisplayMode()707 auto Scheduler::chooseDisplayMode() -> std::pair<DisplayModePtr, GlobalSignals> {
708     ATRACE_CALL();
709 
710     const auto configs = holdRefreshRateConfigs();
711 
712     // If Display Power is not in normal operation we want to be in performance mode. When coming
713     // back to normal mode, a grace period is given with DisplayPowerTimer.
714     if (mDisplayPowerTimer &&
715         (mPolicy.displayPowerMode != hal::PowerMode::ON ||
716          mPolicy.displayPowerTimer == TimerState::Reset)) {
717         constexpr GlobalSignals kNoSignals;
718         return {configs->getMaxRefreshRateByPolicy(), kNoSignals};
719     }
720 
721     const GlobalSignals signals{.touch = mTouchTimer && mPolicy.touch == TouchState::Active,
722                                 .idle = mPolicy.idleTimer == TimerState::Expired};
723 
724     return configs->getBestRefreshRate(mPolicy.contentRequirements, signals);
725 }
726 
getPreferredDisplayMode()727 DisplayModePtr Scheduler::getPreferredDisplayMode() {
728     std::lock_guard<std::mutex> lock(mPolicyLock);
729     // Make sure the stored mode is up to date.
730     mPolicy.mode = chooseDisplayMode().first;
731     return mPolicy.mode;
732 }
733 
onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline & timeline)734 void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline) {
735     std::lock_guard<std::mutex> lock(mVsyncTimelineLock);
736     mLastVsyncPeriodChangeTimeline = std::make_optional(timeline);
737 
738     const auto maxAppliedTime = systemTime() + MAX_VSYNC_APPLIED_TIME.count();
739     if (timeline.newVsyncAppliedTimeNanos > maxAppliedTime) {
740         mLastVsyncPeriodChangeTimeline->newVsyncAppliedTimeNanos = maxAppliedTime;
741     }
742 }
743 
onPostComposition(nsecs_t presentTime)744 bool Scheduler::onPostComposition(nsecs_t presentTime) {
745     std::lock_guard<std::mutex> lock(mVsyncTimelineLock);
746     if (mLastVsyncPeriodChangeTimeline && mLastVsyncPeriodChangeTimeline->refreshRequired) {
747         if (presentTime < mLastVsyncPeriodChangeTimeline->refreshTimeNanos) {
748             // We need to composite again as refreshTimeNanos is still in the future.
749             return true;
750         }
751 
752         mLastVsyncPeriodChangeTimeline->refreshRequired = false;
753     }
754     return false;
755 }
756 
onActiveDisplayAreaChanged(uint32_t displayArea)757 void Scheduler::onActiveDisplayAreaChanged(uint32_t displayArea) {
758     mLayerHistory.setDisplayArea(displayArea);
759 }
760 
setGameModeRefreshRateForUid(FrameRateOverride frameRateOverride)761 void Scheduler::setGameModeRefreshRateForUid(FrameRateOverride frameRateOverride) {
762     if (frameRateOverride.frameRateHz > 0.f && frameRateOverride.frameRateHz < 1.f) {
763         return;
764     }
765 
766     mFrameRateOverrideMappings.setGameModeRefreshRateForUid(frameRateOverride);
767 }
768 
setPreferredRefreshRateForUid(FrameRateOverride frameRateOverride)769 void Scheduler::setPreferredRefreshRateForUid(FrameRateOverride frameRateOverride) {
770     if (frameRateOverride.frameRateHz > 0.f && frameRateOverride.frameRateHz < 1.f) {
771         return;
772     }
773 
774     mFrameRateOverrideMappings.setPreferredRefreshRateForUid(frameRateOverride);
775 }
776 
getPreviousVsyncFrom(nsecs_t expectedPresentTime) const777 std::chrono::steady_clock::time_point Scheduler::getPreviousVsyncFrom(
778         nsecs_t expectedPresentTime) const {
779     const auto presentTime = std::chrono::nanoseconds(expectedPresentTime);
780     const auto vsyncPeriod = std::chrono::nanoseconds(mVsyncSchedule->getTracker().currentPeriod());
781     return std::chrono::steady_clock::time_point(presentTime - vsyncPeriod);
782 }
783 
784 } // namespace android::scheduler
785