1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "core/components_ng/manager/display_sync/ui_display_sync_manager.h"
16 
17 namespace OHOS::Ace {
18 const std::vector<int32_t> UIDisplaySyncManager::REFRESH_RATE_LIST = { 90, 120, 144 };
19 
DispatchFunc(int64_t nanoTimestamp)20 void UIDisplaySyncManager::DispatchFunc(int64_t nanoTimestamp)
21 {
22     CheckSkipEnableProperty();
23     displaySyncRange_->Reset();
24 
25     if (uiDisplaySyncMap_.empty()) {
26         return;
27     }
28 
29     IdToDisplaySyncMap backupedMap(uiDisplaySyncMap_);
30 
31     int32_t VSyncPeriod = GetVsyncPeriod();
32     for (const auto& [Id, weakDisplaySync] : backupedMap) {
33         auto displaySync = weakDisplaySync.Upgrade();
34         if (displaySync) {
35             displaySync->CheckRate(sourceVsyncRate_, refreshRateMode_);
36             displaySync->UpdateData(nanoTimestamp, VSyncPeriod);
37             if (IsAutoRefreshRateMode() ||
38                 (IsNonAutoRefreshRateMode() && IsSupportSkip())) {
39                 displaySync->JudgeWhetherSkip();
40             }
41             displaySync->OnFrame();
42 
43             auto rateRange = displaySync->GetDisplaySyncData()->rateRange_;
44             if (rateRange->IsValid()) {
45                 displaySyncRange_->Merge(*rateRange);
46             }
47             TAG_LOGD(AceLogTag::ACE_DISPLAY_SYNC, "UIDisplaySyncMapSize:%{public}d Id:%{public}d"
48                 "FrameRateRange: {%{public}d, %{public}d, %{public}d}",
49                 static_cast<int32_t>(uiDisplaySyncMap_.size()), static_cast<int32_t>(displaySync->GetId()),
50                 rateRange->min_, rateRange->max_, rateRange->preferred_);
51         } else {
52             uiDisplaySyncMap_.erase(Id);
53         }
54     }
55 
56     return;
57 }
58 
HasDisplaySync(const RefPtr<UIDisplaySync> & displaySync)59 bool UIDisplaySyncManager::HasDisplaySync(const RefPtr<UIDisplaySync>& displaySync)
60 {
61     if (displaySync && uiDisplaySyncMap_.count(displaySync->GetId())) {
62         return true;
63     }
64     return false;
65 }
66 
AddDisplaySync(const RefPtr<UIDisplaySync> & displaySync)67 bool UIDisplaySyncManager::AddDisplaySync(const RefPtr<UIDisplaySync>& displaySync)
68 {
69     if (HasDisplaySync(displaySync)) {
70         TAG_LOGD(AceLogTag::ACE_DISPLAY_SYNC, "DisplaySyncId[%{public}d] is existed.",
71             static_cast<int32_t>(displaySync->GetId()));
72         return false;
73     }
74     ACE_SCOPED_TRACE("AddDisplaySync Id:%d", static_cast<int32_t>(displaySync->GetId()));
75     uiDisplaySyncMap_[displaySync->GetId()] = displaySync;
76     TAG_LOGD(AceLogTag::ACE_DISPLAY_SYNC, "AddDisplaySync MapSize: %{public}d expected: %{public}d.",
77         static_cast<int32_t>(uiDisplaySyncMap_.size()), displaySync->GetDisplaySyncData()->rateRange_->preferred_);
78     displaySync->JudgeWhetherRequestFrame();
79     return true;
80 }
81 
RemoveDisplaySync(const RefPtr<UIDisplaySync> & displaySync)82 bool UIDisplaySyncManager::RemoveDisplaySync(const RefPtr<UIDisplaySync>& displaySync)
83 {
84     if (HasDisplaySync(displaySync)) {
85         ACE_SCOPED_TRACE("RemoveDisplaySync Id:%d", static_cast<int32_t>(displaySync->GetId()));
86         uiDisplaySyncMap_.erase(displaySync->GetId());
87         TAG_LOGD(AceLogTag::ACE_DISPLAY_SYNC, "RemoveDisplaySync MapSize: %{public}d expected: %{public}d.",
88             static_cast<int32_t>(uiDisplaySyncMap_.size()),
89             displaySync->GetDisplaySyncData()->rateRange_->preferred_);
90         return true;
91     }
92     return false;
93 }
94 
SetVsyncRate(int32_t vsyncRate)95 bool UIDisplaySyncManager::SetVsyncRate(int32_t vsyncRate)
96 {
97     if (vsyncRate < 0) {
98         return false;
99     }
100 
101     if (sourceVsyncRate_ == vsyncRate) {
102         return false;
103     }
104     sourceVsyncRate_ = vsyncRate;
105     return true;
106 }
107 
GetVsyncRate() const108 int32_t UIDisplaySyncManager::GetVsyncRate() const
109 {
110     return sourceVsyncRate_;
111 }
112 
SetVsyncPeriod(int64_t vsyncPeriod)113 bool UIDisplaySyncManager::SetVsyncPeriod(int64_t vsyncPeriod)
114 {
115     if (vsyncPeriod < 0) {
116         return false;
117     }
118 
119     if (vsyncPeriod_ == vsyncPeriod) {
120         return false;
121     }
122     vsyncPeriod_ = vsyncPeriod;
123 
124     int32_t rate = static_cast<int32_t>(std::ceil(SECOND_IN_NANO / vsyncPeriod_));
125     std::call_once(computeFactorsFlag_, [this]() { FindAllRefreshRateFactors(); });
126     int32_t refreshRate = FindMatchedRefreshRate(rate);
127     SetVsyncRate(refreshRate);
128 
129     return true;
130 }
131 
GetVsyncPeriod() const132 int64_t UIDisplaySyncManager::GetVsyncPeriod() const
133 {
134     return vsyncPeriod_;
135 }
136 
SetRefreshRateMode(int32_t refreshRateMode)137 bool UIDisplaySyncManager::SetRefreshRateMode(int32_t refreshRateMode)
138 {
139     if (refreshRateMode < -1) {
140         return false;
141     }
142 
143     if (refreshRateMode_ == refreshRateMode) {
144         return false;
145     }
146 
147     refreshRateMode_ = refreshRateMode;
148     return true;
149 }
150 
GetRefreshRateMode() const151 int32_t UIDisplaySyncManager::GetRefreshRateMode() const
152 {
153     return refreshRateMode_;
154 }
155 
GetDisplaySyncRate() const156 int32_t UIDisplaySyncManager::GetDisplaySyncRate() const
157 {
158     int32_t displaySyncRate = displaySyncRange_->preferred_;
159     return displaySyncRate;
160 }
161 
GetUIDisplaySyncMap() const162 IdToDisplaySyncMap UIDisplaySyncManager::GetUIDisplaySyncMap() const
163 {
164     return uiDisplaySyncMap_;
165 }
166 
CheckSkipEnableProperty()167 void UIDisplaySyncManager::CheckSkipEnableProperty()
168 {
169     std::call_once(isEnablePropertyFlag_, [this] () {
170         supportSkipEnabled_ = SystemProperties::GetDisplaySyncSkipEnabled();
171     });
172 }
173 
IsSupportSkip() const174 bool UIDisplaySyncManager::IsSupportSkip() const
175 {
176     return supportSkipEnabled_;
177 }
178 
IsAutoRefreshRateMode() const179 bool UIDisplaySyncManager::IsAutoRefreshRateMode() const
180 {
181     return refreshRateMode_ == static_cast<int32_t>(RefreshRateMode::REFRESHRATE_MODE_AUTO);
182 }
183 
IsNonAutoRefreshRateMode() const184 bool UIDisplaySyncManager::IsNonAutoRefreshRateMode() const
185 {
186     return refreshRateMode_ != static_cast<int32_t>(RefreshRateMode::REFRESHRATE_MODE_AUTO);
187 }
188 
FindRefreshRateFactors(int32_t refreshRate)189 std::set<int32_t> UIDisplaySyncManager::FindRefreshRateFactors(int32_t refreshRate)
190 {
191     std::set<int32_t> refreshRateFactors;
192     for (int32_t i = 1; i * i <= refreshRate; ++i) {
193         if (refreshRate % i == 0) {
194             refreshRateFactors.insert(i);
195             if (i != refreshRate / i) {
196                 refreshRateFactors.insert(refreshRate / i);
197             }
198         }
199     }
200     return refreshRateFactors;
201 }
202 
FindMatchedRefreshRate(int32_t target)203 int32_t UIDisplaySyncManager::FindMatchedRefreshRate(int32_t target)
204 {
205     auto it = std::lower_bound(refreshRateFactors_.begin(), refreshRateFactors_.end(), target);
206     if (it == refreshRateFactors_.begin()) {
207         return *it;
208     } else if (it == refreshRateFactors_.end()) {
209         return *(it - 1);
210     }
211     return std::abs(*it - target) < std::abs(*(it - 1) - target) ? *it : *(it - 1);
212 }
213 
FindAllRefreshRateFactors()214 void UIDisplaySyncManager::FindAllRefreshRateFactors()
215 {
216     std::set<int32_t> allFactors;
217     for (const auto& refreshRate : REFRESH_RATE_LIST) {
218         std::set<int32_t> factors = FindRefreshRateFactors(refreshRate);
219         allFactors.insert(factors.begin(), factors.end());
220     }
221     refreshRateFactors_.clear();
222     std::copy(allFactors.begin(), allFactors.end(), std::back_inserter(refreshRateFactors_));
223     return;
224 }
225 
GetAnimatorRate()226 int32_t UIDisplaySyncManager::GetAnimatorRate()
227 {
228     std::priority_queue<int32_t> emptyQue;
229     std::swap(maxAnimatorRateHap_, emptyQue);
230 
231     if (uiDisplaySyncMap_.empty()) {
232         return INVALID_ANIMATOR_EXPECTED_RATE;
233     }
234 
235     IdToDisplaySyncMap backupedMap(uiDisplaySyncMap_);
236     for (const auto& [Id, weakDisplaySync] : backupedMap) {
237         auto displaySync = weakDisplaySync.Upgrade();
238         if (displaySync) {
239             maxAnimatorRateHap_.push(displaySync->GetAnimatorExpectedRate());
240         } else {
241             uiDisplaySyncMap_.erase(Id);
242         }
243     }
244 
245     if (maxAnimatorRateHap_.empty()) {
246         return INVALID_ANIMATOR_EXPECTED_RATE;
247     }
248     int32_t currMaxAnimatorExpectedRate = maxAnimatorRateHap_.top();
249     return currMaxAnimatorExpectedRate;
250 }
251 
IsAnimatorStopped()252 bool UIDisplaySyncManager::IsAnimatorStopped()
253 {
254     if (GetAnimatorRate() == INVALID_ANIMATOR_EXPECTED_RATE) {
255         return true;
256     }
257     return false;
258 }
259 
UIDisplaySyncManager()260 UIDisplaySyncManager::UIDisplaySyncManager() {}
261 
~UIDisplaySyncManager()262 UIDisplaySyncManager::~UIDisplaySyncManager() noexcept
263 {
264     uiDisplaySyncMap_.clear();
265 }
266 } // namespace OHOS::Ace
267