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 "VideoFrameRateCalculator.h"
20 
21 #include <numeric>
22 
23 #include "../Utils.h"
24 
25 namespace android::hardware::graphics::composer {
26 
VideoFrameRateCalculator(EventQueue * eventQueue,const VideoFrameRateCalculatorParameters & params)27 VideoFrameRateCalculator::VideoFrameRateCalculator(EventQueue* eventQueue,
28                                                    const VideoFrameRateCalculatorParameters& params)
29       : mEventQueue(eventQueue), mParams(params) {
30     mName = "RefreshRateCalculator-Video";
31 
32     mParams.mMaxInterestedFrameRate = std::min(mMaxFrameRate, mParams.mMaxInterestedFrameRate);
33     mParams.mMinInterestedFrameRate = std::max(1, mParams.mMinInterestedFrameRate);
34 
35     mRefreshRateCalculator =
36             std::make_unique<PeriodRefreshRateCalculator>(mEventQueue, params.mPeriodParams);
37     mRefreshRateCalculator->setName("RefreshRateCalculator-Period-Worker");
38     mRefreshRateCalculator->registerRefreshRateChangeCallback(
39             std::bind(&VideoFrameRateCalculator::onReportRefreshRate, this, std::placeholders::_1));
40 }
41 
getRefreshRate() const42 int VideoFrameRateCalculator::getRefreshRate() const {
43     if ((mLastVideoFrameRate >= mParams.mMinInterestedFrameRate) &&
44         (mLastVideoFrameRate <= mParams.mMaxInterestedFrameRate)) {
45         return mLastVideoFrameRate;
46     }
47     return kDefaultInvalidRefreshRate;
48 }
49 
onPowerStateChange(int from,int to)50 void VideoFrameRateCalculator::onPowerStateChange(int from, int to) {
51     if (to != HWC_POWER_MODE_NORMAL) {
52         setEnabled(false);
53     } else {
54         if (from == HWC_POWER_MODE_NORMAL) {
55             ALOGE("Disregard power state change notification by staying current power state.");
56             return;
57         }
58         setEnabled(true);
59     }
60 }
61 
onPresentInternal(int64_t presentTimeNs,int flag)62 void VideoFrameRateCalculator::onPresentInternal(int64_t presentTimeNs, int flag) {
63     if (hasPresentFrameFlag(flag, PresentFrameFlag::kPresentingWhenDoze)) {
64         return;
65     }
66     if (hasPresentFrameFlag(flag, PresentFrameFlag::kIsYuv)) {
67         mRefreshRateCalculator->onPresentInternal(presentTimeNs, flag);
68     } else {
69         reset();
70     }
71 }
72 
reset()73 void VideoFrameRateCalculator::reset() {
74     setNewRefreshRate(kDefaultInvalidRefreshRate);
75     mLastPeriodFrameRate = kDefaultInvalidRefreshRate;
76     mLastPeriodFrameRateRuns = 0;
77     mHistory.clear();
78 }
79 
setEnabled(bool isEnabled)80 void VideoFrameRateCalculator::setEnabled(bool isEnabled) {
81     mRefreshRateCalculator->setEnabled(isEnabled);
82 }
83 
setVrrConfigAttributes(int64_t vsyncPeriodNs,int64_t minFrameIntervalNs)84 void VideoFrameRateCalculator::setVrrConfigAttributes(int64_t vsyncPeriodNs,
85                                                       int64_t minFrameIntervalNs) {
86     RefreshRateCalculator::setVrrConfigAttributes(vsyncPeriodNs, minFrameIntervalNs);
87 
88     mRefreshRateCalculator->setVrrConfigAttributes(vsyncPeriodNs, minFrameIntervalNs);
89 }
90 
onReportRefreshRate(int refreshRate)91 int VideoFrameRateCalculator::onReportRefreshRate(int refreshRate) {
92     if ((mLastPeriodFrameRate != kDefaultInvalidRefreshRate) &&
93         (std::abs(mLastPeriodFrameRate - refreshRate) <= mParams.mDelta) &&
94         (mLastPeriodFrameRate >= mParams.mMinInterestedFrameRate) &&
95         (mLastPeriodFrameRate <= mParams.mMaxInterestedFrameRate)) {
96         ++mLastPeriodFrameRateRuns;
97         mHistory.push_back(refreshRate);
98         while (mHistory.size() > mParams.mWindowSize) {
99             mHistory.pop_front();
100         }
101         if (mLastPeriodFrameRateRuns >= mParams.mMinStableRuns) {
102             int sum = std::accumulate(std::begin(mHistory), std::end(mHistory), 0);
103             mLastPeriodFrameRate = std::round(sum / static_cast<float>(mHistory.size()));
104             setNewRefreshRate(mLastPeriodFrameRate);
105         }
106     } else {
107         mLastPeriodFrameRate = refreshRate;
108         mLastPeriodFrameRateRuns = 1;
109         setNewRefreshRate(kDefaultInvalidRefreshRate);
110         mHistory.clear();
111         mHistory.push_back(refreshRate);
112     }
113     return NO_ERROR;
114 }
115 
setNewRefreshRate(int newRefreshRate)116 void VideoFrameRateCalculator::setNewRefreshRate(int newRefreshRate) {
117     if (newRefreshRate != mLastVideoFrameRate) {
118         mLastVideoFrameRate = newRefreshRate;
119         ATRACE_INT(mName.c_str(), newRefreshRate);
120         if (mRefreshRateChangeCallback) {
121             if ((mLastVideoFrameRate >= mParams.mMinInterestedFrameRate) &&
122                 (mLastVideoFrameRate <= mParams.mMaxInterestedFrameRate)) {
123                 mRefreshRateChangeCallback(mLastVideoFrameRate);
124             }
125         }
126     }
127 }
128 
129 } // namespace android::hardware::graphics::composer
130