1 /*
2  * Copyright (C) 2024 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 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
18 
19 #include "InstantRefreshRateCalculator.h"
20 
21 #include <algorithm>
22 
23 namespace android::hardware::graphics::composer {
24 
InstantRefreshRateCalculator(EventQueue * eventQueue)25 InstantRefreshRateCalculator::InstantRefreshRateCalculator(EventQueue* eventQueue)
26       : InstantRefreshRateCalculator(eventQueue, kDefaultMaxValidTimeNs) {}
27 
InstantRefreshRateCalculator(EventQueue * eventQueue,int64_t maxValidTimeNs)28 InstantRefreshRateCalculator::InstantRefreshRateCalculator(EventQueue* eventQueue,
29                                                            int64_t maxValidTimeNs)
30       : mEventQueue(eventQueue), mMaxValidTimeNs(maxValidTimeNs) {
31     mName = "RefreshRateCalculator-Instant";
32     mTimeoutEvent.mEventType = VrrControllerEventType::kInstantRefreshRateCalculatorUpdate;
33     mTimeoutEvent.mFunctor =
34             std::move(std::bind(&InstantRefreshRateCalculator::updateRefreshRate, this));
35 }
36 
getRefreshRate() const37 int InstantRefreshRateCalculator::getRefreshRate() const {
38     return mLastRefreshRate;
39 }
40 
onPresentInternal(int64_t presentTimeNs,int flag)41 void InstantRefreshRateCalculator::onPresentInternal(int64_t presentTimeNs, int flag) {
42     if (hasPresentFrameFlag(flag, PresentFrameFlag::kPresentingWhenDoze)) {
43         return;
44     }
45     if (mLastPresentTimeNs != kDefaultInvalidPresentTimeNs) {
46         if (presentTimeNs <= mLastPresentTimeNs) {
47             // Disregard incoming frames that are out of sequence.
48             return;
49         }
50         if (isOutdated(presentTimeNs)) {
51             reset();
52         } else {
53             auto numVsync = durationToVsync((presentTimeNs - mLastPresentTimeNs));
54             numVsync = std::max(mMinVsyncNum, std::min(mVsyncRate, numVsync));
55             auto currentRefreshRate = roundDivide(mVsyncRate, numVsync);
56             currentRefreshRate = std::max(1, currentRefreshRate);
57             setNewRefreshRate(currentRefreshRate);
58         }
59     }
60     mLastPresentTimeNs = presentTimeNs;
61 
62     mEventQueue->dropEvent(VrrControllerEventType::kInstantRefreshRateCalculatorUpdate);
63     mTimeoutEvent.mWhenNs = presentTimeNs + mMaxValidTimeNs;
64     mEventQueue->mPriorityQueue.emplace(mTimeoutEvent);
65 }
66 
reset()67 void InstantRefreshRateCalculator::reset() {
68     mLastPresentTimeNs = kDefaultInvalidPresentTimeNs;
69     setNewRefreshRate(kDefaultInvalidRefreshRate);
70 }
71 
setEnabled(bool isEnabled)72 void InstantRefreshRateCalculator::setEnabled(bool isEnabled) {
73     if (!isEnabled) {
74         mEventQueue->dropEvent(VrrControllerEventType::kInstantRefreshRateCalculatorUpdate);
75     } else {
76         mTimeoutEvent.mWhenNs = getSteadyClockTimeNs() + mMaxValidTimeNs;
77         mEventQueue->mPriorityQueue.emplace(mTimeoutEvent);
78     }
79 }
80 
isOutdated(int64_t timeNs) const81 bool InstantRefreshRateCalculator::isOutdated(int64_t timeNs) const {
82     return (mLastPresentTimeNs == kDefaultInvalidPresentTimeNs) ||
83             ((timeNs - mLastPresentTimeNs) > mMaxValidTimeNs);
84 }
85 
setNewRefreshRate(int newRefreshRate)86 void InstantRefreshRateCalculator::setNewRefreshRate(int newRefreshRate) {
87     if (newRefreshRate != mLastRefreshRate) {
88         mLastRefreshRate = newRefreshRate;
89         ATRACE_INT(mName.c_str(), newRefreshRate);
90         if (mRefreshRateChangeCallback) {
91             mRefreshRateChangeCallback(newRefreshRate);
92         }
93     }
94 }
95 
updateRefreshRate()96 int InstantRefreshRateCalculator::updateRefreshRate() {
97     if (isOutdated(getSteadyClockTimeNs())) {
98         reset();
99     }
100     return NO_ERROR;
101 }
102 
103 } // namespace android::hardware::graphics::composer
104