1 /*
2  * Copyright (c) 2021 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 
16 #include "vsync_generator.h"
17 #include "vsync_distributor.h"
18 #include <cstdint>
19 #include <mutex>
20 #include <scoped_bytrace.h>
21 #include <sched.h>
22 #include <sys/resource.h>
23 #include <string>
24 #include <parameters.h>
25 #include "vsync_log.h"
26 #include <ctime>
27 #include <vsync_sampler.h>
28 #include <rs_trace.h>
29 #include "scoped_trace_fmt.h"
30 
31 #ifdef COMPOSER_SCHED_ENABLE
32 #include "if_system_ability_manager.h"
33 #include <iservice_registry.h>
34 #include "system_ability_definition.h"
35 #endif
36 
37 namespace OHOS {
38 namespace Rosen {
39 namespace impl {
40 namespace {
SystemTime()41 static int64_t SystemTime()
42 {
43     timespec t = {};
44     clock_gettime(CLOCK_MONOTONIC, &t);
45     return int64_t(t.tv_sec) * 1000000000LL + t.tv_nsec; // 1000000000ns == 1s
46 }
47 
48 // 1.5ms
49 constexpr int64_t maxWaleupDelay = 1500000;
50 constexpr int32_t THREAD_PRIORTY = -6;
51 constexpr int32_t SCHED_PRIORITY = 2;
52 constexpr int64_t errorThreshold = 500000;
53 constexpr int32_t MAX_REFRESHRATE_DEVIATION = 5; // ±5Hz
54 constexpr int64_t PERIOD_CHECK_THRESHOLD = 1000000; // 1000000ns == 1.0ms
55 constexpr int64_t REFRESH_PERIOD = 16666667; // 16666667ns == 16.666667ms
56 constexpr int64_t DEFAULT_SOFT_VSYNC_PERIOD = 16000000; // 16000000ns == 16ms
57 
SetThreadHighPriority()58 static void SetThreadHighPriority()
59 {
60     setpriority(PRIO_PROCESS, 0, THREAD_PRIORTY);
61     struct sched_param param = {0};
62     param.sched_priority = SCHED_PRIORITY;
63     sched_setscheduler(0, SCHED_FIFO, &param);
64 }
65 
IsPcType()66 static bool IsPcType()
67 {
68     static bool isPc = (system::GetParameter("const.product.devicetype", "pc") == "pc") ||
69                        (system::GetParameter("const.product.devicetype", "pc") == "2in1");
70     return isPc;
71 }
72 
IsPCRefreshRateLock60()73 static bool IsPCRefreshRateLock60()
74 {
75     static bool isPCRefreshRateLock60 =
76         (std::atoi(system::GetParameter("persist.pc.refreshrate.lock60", "0").c_str()) != 0);
77     return isPCRefreshRateLock60;
78 }
79 }
80 
81 std::once_flag VSyncGenerator::createFlag_;
82 sptr<OHOS::Rosen::VSyncGenerator> VSyncGenerator::instance_ = nullptr;
83 
CalculateRefreshRate(int64_t period)84 uint32_t CalculateRefreshRate(int64_t period)
85 {
86     static struct {
87         int min;
88         int max;
89         int refreshRate;
90     } rateSections[] = {
91         {30000000, 35000000, 30}, // 30000000ns, 35000000ns
92         {15000000, 18000000, 60}, // 15000000ns, 18000000ns
93         {10000000, 12000000, 90}, // 10000000ns, 12000000ns
94         {7500000, 9000000, 120}}; // 7500000ns, 9000000ns
95     for (const auto& rateSection : rateSections) {
96         if (period > rateSection.min && period < rateSection.max) {
97             return rateSection.refreshRate;
98         }
99     }
100     return 0;
101 }
102 
103 sptr<OHOS::Rosen::VSyncGenerator> VSyncGenerator::GetInstance() noexcept
104 {
105     std::call_once(createFlag_, []() {
106         instance_ = new VSyncGenerator();
107     });
108 
109     return instance_;
110 }
111 
112 void VSyncGenerator::DeleteInstance() noexcept
113 {
114     instance_ = nullptr;
115 }
116 
VSyncGenerator()117 VSyncGenerator::VSyncGenerator()
118 {
119     if (IsPcType() && IsPCRefreshRateLock60()) {
120         period_ = REFRESH_PERIOD;
121     } else {
122         period_ = DEFAULT_SOFT_VSYNC_PERIOD;
123     }
124     vsyncThreadRunning_ = true;
125     thread_ = std::thread([this] { this->ThreadLoop(); });
126     pthread_setname_np(thread_.native_handle(), "VSyncGenerator");
127 }
128 
~VSyncGenerator()129 VSyncGenerator::~VSyncGenerator()
130 {
131     {
132         std::unique_lock<std::mutex> locker(mutex_);
133         vsyncThreadRunning_ = false;
134     }
135 
136     if (thread_.joinable()) {
137         con_.notify_all();
138         thread_.join();
139     }
140 }
141 
ListenerVsyncEventCB(int64_t occurTimestamp, int64_t nextTimeStamp, int64_t occurReferenceTime, bool isWakeup)142 void VSyncGenerator::ListenerVsyncEventCB(int64_t occurTimestamp, int64_t nextTimeStamp,
143     int64_t occurReferenceTime, bool isWakeup)
144 {
145     SCOPED_DEBUG_TRACE_FMT("occurTimestamp:%ld, nextTimeStamp:%ld", occurTimestamp, nextTimeStamp);
146     std::vector<Listener> listeners;
147     uint32_t vsyncMaxRefreshRate = 360;
148     {
149         std::unique_lock<std::mutex> locker(mutex_);
150         vsyncMaxRefreshRate = vsyncMaxRefreshRate_;
151         int64_t newOccurTimestamp = SystemTime();
152         if (isWakeup) {
153             UpdateWakeupDelay(newOccurTimestamp, nextTimeStamp);
154         }
155         if (vsyncMode_ == VSYNC_MODE_LTPO) {
156             listeners = GetListenerTimeoutedLTPO(occurTimestamp, occurReferenceTime);
157         } else {
158             listeners = GetListenerTimeouted(newOccurTimestamp, occurTimestamp, occurReferenceTime);
159         }
160         expectTimeFlag_ = false;
161     }
162     RS_TRACE_NAME_FMT("GenerateVsyncCount:%lu, period:%ld, currRefreshRate_:%u, vsyncMode_:%d",
163         listeners.size(), periodRecord_, currRefreshRate_, vsyncMode_);
164     for (uint32_t i = 0; i < listeners.size(); i++) {
165         RS_TRACE_NAME_FMT("listener phase is %ld", listeners[i].phase_);
166         if (listeners[i].callback_ != nullptr) {
167             listeners[i].callback_->OnVSyncEvent(listeners[i].lastTime_,
168                 periodRecord_, currRefreshRate_, vsyncMode_, vsyncMaxRefreshRate);
169         }
170     }
171 }
172 
ThreadLoop()173 void VSyncGenerator::ThreadLoop()
174 {
175 #ifdef COMPOSER_SCHED_ENABLE
176     SubScribeSystemAbility();
177 #endif
178     // set thread priorty
179     SetThreadHighPriority();
180 
181     int64_t occurTimestamp = 0;
182     int64_t nextTimeStamp = 0;
183     int64_t occurReferenceTime = 0;
184     while (true) {
185         {
186             std::unique_lock<std::mutex> locker(mutex_);
187             if (vsyncThreadRunning_ == false) {
188                 break;
189             }
190             UpdateVSyncModeLocked();
191             occurReferenceTime = referenceTime_;
192             phaseRecord_ = phase_;
193             periodRecord_ = period_;
194             if (period_ == 0) {
195                 ScopedBytrace func("VSyncGenerator: period not valid");
196                 if (vsyncThreadRunning_ == true) {
197                     con_.wait(locker);
198                 }
199                 continue;
200             }
201             occurTimestamp = SystemTime();
202             nextTimeStamp = ComputeNextVSyncTimeStamp(occurTimestamp, occurReferenceTime);
203             if (nextTimeStamp == INT64_MAX) {
204                 ScopedBytrace func("VSyncGenerator: there has no listener");
205                 if (vsyncThreadRunning_ == true) {
206                     con_.wait(locker);
207                 }
208                 continue;
209             } else if (vsyncMode_ == VSYNC_MODE_LTPO &&
210                 UpdateChangeDataLocked(occurTimestamp, occurReferenceTime, nextTimeStamp)) {
211                 ScopedBytrace func("VSyncGenerator: LTPO mode change");
212                 bool clearAllSamplesFlag = clearAllSamplesFlag_;
213                 clearAllSamplesFlag_ = false;
214                 locker.unlock();
215                 ClearAllSamplesInternal(clearAllSamplesFlag);
216                 if (appVSyncDistributor_ != nullptr) {
217                     appVSyncDistributor_->RecordVsyncModeChange(currRefreshRate_, period_);
218                 }
219                 if (rsVSyncDistributor_ != nullptr) {
220                     rsVSyncDistributor_->RecordVsyncModeChange(currRefreshRate_, period_);
221                 }
222                 continue;
223             }
224         }
225 
226         WaitForTimeout(occurTimestamp, nextTimeStamp, occurReferenceTime);
227     }
228 }
229 
WaitForTimeout(int64_t occurTimestamp, int64_t nextTimeStamp, int64_t occurReferenceTime)230 void VSyncGenerator::WaitForTimeout(int64_t occurTimestamp, int64_t nextTimeStamp, int64_t occurReferenceTime)
231 {
232     bool isWakeup = false;
233     if (occurTimestamp < nextTimeStamp) {
234         if (nextTimeStamp - occurTimestamp > periodRecord_ * 3 / 2) { // 3/2 means no more than 1.5 period
235             RS_TRACE_NAME_FMT("WaitForTimeout occurTimestamp:%ld, nextTimeStamp:%ld", occurTimestamp, nextTimeStamp);
236         }
237         std::unique_lock<std::mutex> lck(waitForTimeoutMtx_);
238         auto err = waitForTimeoutCon_.wait_for(lck, std::chrono::nanoseconds(nextTimeStamp - occurTimestamp));
239         if (err == std::cv_status::timeout) {
240             isWakeup = true;
241         } else {
242             ScopedBytrace func("VSyncGenerator::ThreadLoop::Continue");
243             return;
244         }
245     }
246     ListenerVsyncEventCB(occurTimestamp, nextTimeStamp, occurReferenceTime, isWakeup);
247 }
248 
ChangeListenerOffsetInternal()249 bool VSyncGenerator::ChangeListenerOffsetInternal()
250 {
251     if (changingPhaseOffset_.cb == nullptr) {
252         return true;
253     }
254     auto it = listeners_.begin();
255     for (; it < listeners_.end(); it++) {
256         if (it->callback_ == changingPhaseOffset_.cb) {
257             break;
258         }
259     }
260     int64_t phaseOffset = pulse_ * changingPhaseOffset_.phaseByPulseNum;
261     if (it != listeners_.end()) {
262         it->phase_ = phaseOffset;
263     }
264 
265     it = listenersRecord_.begin();
266     for (; it < listenersRecord_.end(); it++) {
267         if (it->callback_ == changingPhaseOffset_.cb) {
268             break;
269         }
270     }
271     if (it == listenersRecord_.end()) {
272         return false;
273     }
274     if (it->callback_ != nullptr) {
275         it->callback_->OnPhaseOffsetChanged(phaseOffset);
276     }
277     changingPhaseOffset_ = {}; // reset
278     return true;
279 }
280 
ChangeListenerRefreshRatesInternal()281 bool VSyncGenerator::ChangeListenerRefreshRatesInternal()
282 {
283     if (changingRefreshRates_.cb == nullptr) {
284         return true;
285     }
286     auto it = listenersRecord_.begin();
287     for (; it < listenersRecord_.end(); it++) {
288         if (it->callback_ == changingRefreshRates_.cb) {
289             break;
290         }
291     }
292     if (it == listenersRecord_.end()) {
293         return false;
294     }
295     if (it->callback_ != nullptr) {
296         it->callback_->OnConnsRefreshRateChanged(changingRefreshRates_.refreshRates);
297     }
298     // reset
299     changingRefreshRates_.cb = nullptr;
300     changingRefreshRates_.refreshRates.clear();
301     changingRefreshRates_ = {};
302     return true;
303 }
304 
UpdateWakeupDelay(int64_t occurTimestamp, int64_t nextTimeStamp)305 void VSyncGenerator::UpdateWakeupDelay(int64_t occurTimestamp, int64_t nextTimeStamp)
306 {
307     // 63, 1 / 64
308     wakeupDelay_ = ((wakeupDelay_ * 63) + (occurTimestamp - nextTimeStamp)) / 64;
309     wakeupDelay_ = wakeupDelay_ > maxWaleupDelay ? maxWaleupDelay : wakeupDelay_;
310 }
311 
ComputeNextVSyncTimeStamp(int64_t now, int64_t referenceTime)312 int64_t VSyncGenerator::ComputeNextVSyncTimeStamp(int64_t now, int64_t referenceTime)
313 {
314     int64_t nextVSyncTime = INT64_MAX;
315     for (uint32_t i = 0; i < listeners_.size(); i++) {
316         int64_t t = ComputeListenerNextVSyncTimeStamp(listeners_[i], now, referenceTime);
317         if (t < nextVSyncTime) {
318             nextVSyncTime = t;
319         }
320     }
321 
322     return nextVSyncTime;
323 }
324 
CheckTimingCorrect(int64_t now, int64_t referenceTime, int64_t nextVSyncTime)325 bool VSyncGenerator::CheckTimingCorrect(int64_t now, int64_t referenceTime, int64_t nextVSyncTime)
326 {
327     bool isTimingCorrect = false;
328     for (uint32_t i = 0; i < listeners_.size(); i++) {
329         int64_t t = ComputeListenerNextVSyncTimeStamp(listeners_[i], now, referenceTime);
330         if ((t - nextVSyncTime < errorThreshold) && (listeners_[i].phase_ == 0)) {
331             isTimingCorrect = true;
332         }
333     }
334     return isTimingCorrect;
335 }
336 
UpdateChangeDataLocked(int64_t now, int64_t referenceTime, int64_t nextVSyncTime)337 bool VSyncGenerator::UpdateChangeDataLocked(int64_t now, int64_t referenceTime, int64_t nextVSyncTime)
338 {
339     bool modelChanged = false;
340 
341     // change referenceTime
342     if (expectNextVsyncTime_ > 0) {
343         RS_TRACE_NAME_FMT("UpdateChangeDataLocked, expectNextVsyncTime_:%ld", expectNextVsyncTime_);
344         nextVSyncTime = expectNextVsyncTime_;
345         expectNextVsyncTime_ = 0;
346         referenceTime_ = nextVSyncTime;
347         modelChanged = true;
348         expectTimeFlag_ = true;
349     } else {
350         if (!CheckTimingCorrect(now, referenceTime, nextVSyncTime)) {
351             return false;
352         }
353     }
354 
355     // update generate refreshRate
356     if (needChangeGeneratorRefreshRate_) {
357         currRefreshRate_ = changingGeneratorRefreshRate_;
358         period_ = pulse_ * static_cast<int64_t>(vsyncMaxRefreshRate_ / currRefreshRate_);
359         referenceTime_ = nextVSyncTime;
360         changingGeneratorRefreshRate_ = 0; // reset
361         needChangeGeneratorRefreshRate_ = false;
362         refreshRateIsChanged_ = true;
363         frameRateChanging_ = true;
364         ScopedBytrace trace("frameRateChanging_ = true");
365         targetPeriod_ = period_;
366         clearAllSamplesFlag_ = true;
367         modelChanged = true;
368     }
369 
370     // update phaseOffset
371     if (needChangePhaseOffset_) {
372         bool offsetChangedSucceed = ChangeListenerOffsetInternal();
373         if (offsetChangedSucceed) {
374             needChangePhaseOffset_ = false;
375             modelChanged = true;
376         }
377     }
378 
379     // update VSyncConnections refreshRates
380     if (needChangeRefreshRates_) {
381         bool refreshRatesChangedSucceed = ChangeListenerRefreshRatesInternal();
382         if (refreshRatesChangedSucceed) {
383             needChangeRefreshRates_ = false;
384             modelChanged = true;
385         }
386     }
387 
388     return modelChanged;
389 }
390 
ClearAllSamplesInternal(bool clearAllSamplesFlag)391 void VSyncGenerator::ClearAllSamplesInternal(bool clearAllSamplesFlag)
392 {
393     if (clearAllSamplesFlag) {
394         CreateVSyncSampler()->ClearAllSamples();
395     }
396 }
397 
UpdateVSyncModeLocked()398 void VSyncGenerator::UpdateVSyncModeLocked()
399 {
400     if (pendingVsyncMode_ != VSYNC_MODE_INVALID) {
401         vsyncMode_ = pendingVsyncMode_;
402         pendingVsyncMode_ = VSYNC_MODE_INVALID;
403     }
404 }
405 
ComputeListenerNextVSyncTimeStamp(const Listener& listener, int64_t now, int64_t referenceTime)406 int64_t VSyncGenerator::ComputeListenerNextVSyncTimeStamp(const Listener& listener, int64_t now, int64_t referenceTime)
407 {
408     int64_t lastVSyncTime = listener.lastTime_ + wakeupDelay_;
409     if (now < lastVSyncTime) {
410         now = lastVSyncTime;
411     }
412 
413     now -= referenceTime;
414     int64_t phase = phaseRecord_ + listener.phase_;
415     now -= phase;
416     if (now < 0) {
417         if (vsyncMode_ == VSYNC_MODE_LTPO) {
418             if (expectTimeFlag_ || refreshRateIsChanged_) { // Ensure that nextTime is not earlier than referenceTime.
419                 now += ((-now) / periodRecord_) * periodRecord_;
420             }
421             now -= periodRecord_;
422         } else {
423             now = -periodRecord_;
424         }
425     }
426     int64_t numPeriod = now / periodRecord_;
427     int64_t nextTime = (numPeriod + 1) * periodRecord_ + phase;
428     nextTime += referenceTime;
429 
430     // 3 / 5 and 1 / 10 are just empirical value
431     int64_t threshold = refreshRateIsChanged_ ? (1 * periodRecord_ / 10) : (3 * periodRecord_ / 5);
432     // between 8000000(8ms) and 8500000(8.5ms)
433     if (!refreshRateIsChanged_ && frameRateChanging_ && periodRecord_ > 8000000 && periodRecord_ < 8500000) {
434         threshold = 4 * periodRecord_ / 5; // 4 / 5 is an empirical value
435     }
436     // 3 / 5 just empirical value
437     if (((vsyncMode_ == VSYNC_MODE_LTPS) && (nextTime - listener.lastTime_ < (3 * periodRecord_ / 5))) ||
438         ((vsyncMode_ == VSYNC_MODE_LTPO) && (nextTime - listener.lastTime_ < threshold))) {
439         RS_TRACE_NAME_FMT("ComputeListenerNextVSyncTimeStamp add one more period:%ld, threshold:%ld",
440             periodRecord_, threshold);
441         nextTime += periodRecord_;
442     }
443 
444     nextTime -= wakeupDelay_;
445     return nextTime;
446 }
447 
GetListenerTimeouted( int64_t now, int64_t occurTimestamp, int64_t referenceTime)448 std::vector<VSyncGenerator::Listener> VSyncGenerator::GetListenerTimeouted(
449     int64_t now, int64_t occurTimestamp, int64_t referenceTime)
450 {
451     std::vector<VSyncGenerator::Listener> ret;
452     for (uint32_t i = 0; i < listeners_.size(); i++) {
453         int64_t t = ComputeListenerNextVSyncTimeStamp(listeners_[i], occurTimestamp, referenceTime);
454         if (t < now || (t - now < errorThreshold)) {
455             listeners_[i].lastTime_ = t;
456             ret.push_back(listeners_[i]);
457         }
458     }
459     return ret;
460 }
461 
GetListenerTimeoutedLTPO(int64_t now, int64_t referenceTime)462 std::vector<VSyncGenerator::Listener> VSyncGenerator::GetListenerTimeoutedLTPO(int64_t now, int64_t referenceTime)
463 {
464     std::vector<VSyncGenerator::Listener> ret;
465     for (uint32_t i = 0; i < listeners_.size(); i++) {
466         int64_t t = ComputeListenerNextVSyncTimeStamp(listeners_[i], now, referenceTime);
467         if (t - SystemTime() < errorThreshold) {
468             listeners_[i].lastTime_ = t;
469             ret.push_back(listeners_[i]);
470         }
471     }
472     refreshRateIsChanged_ = false;
473     return ret;
474 }
475 
UpdatePeriodLocked(int64_t period)476 VsyncError VSyncGenerator::UpdatePeriodLocked(int64_t period)
477 {
478     VsyncError ret = VSYNC_ERROR_OK;
479     uint32_t refreshRate = JudgeRefreshRateLocked(period);
480     if ((pendingVsyncMode_ == VSYNC_MODE_LTPO) || (vsyncMode_ == VSYNC_MODE_LTPO)) {
481         if ((refreshRate != 0) && ((currRefreshRate_ == refreshRate) || currRefreshRate_ == 0)) {
482             period_ = period;
483         } else {
484             RS_TRACE_NAME_FMT("update period failed, refreshRate:%u, currRefreshRate_:%d",
485                 refreshRate, currRefreshRate_);
486             VLOGE("update period failed, refreshRate:%{public}u, currRefreshRate_:%{public}u, period:" VPUBI64,
487                                     refreshRate, currRefreshRate_, period);
488             ret = VSYNC_ERROR_API_FAILED;
489         }
490     } else {
491         if (period != 0) {
492             period_ = period;
493         } else {
494             ret = VSYNC_ERROR_API_FAILED;
495         }
496     }
497     return ret;
498 }
499 
UpdateReferenceTimeLocked(int64_t referenceTime)500 VsyncError VSyncGenerator::UpdateReferenceTimeLocked(int64_t referenceTime)
501 {
502     if ((pendingVsyncMode_ == VSYNC_MODE_LTPO) || (vsyncMode_ == VSYNC_MODE_LTPO)) {
503         referenceTime_ = referenceTime - referenceTimeOffsetPulseNum_ * pulse_;
504     } else {
505         referenceTime_ = referenceTime;
506     }
507     return VSYNC_ERROR_OK;
508 }
509 
SubScribeSystemAbility()510 void VSyncGenerator::SubScribeSystemAbility()
511 {
512     VLOGD("%{public}s", __func__);
513     sptr<ISystemAbilityManager> systemAbilityManager =
514         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
515     if (!systemAbilityManager) {
516         VLOGE("%{public}s failed to get system ability manager client", __func__);
517         return;
518     }
519     std::string threadName = "VSyncGenerator";
520     std::string strUid = std::to_string(getuid());
521     std::string strPid = std::to_string(getpid());
522     std::string strTid = std::to_string(gettid());
523 
524     saStatusChangeListener_ = new VSyncSystemAbilityListener(threadName, strUid, strPid, strTid);
525     int32_t ret = systemAbilityManager->SubscribeSystemAbility(RES_SCHED_SYS_ABILITY_ID, saStatusChangeListener_);
526     if (ret != ERR_OK) {
527         VLOGE("%{public}s subscribe system ability %{public}d failed.", __func__, RES_SCHED_SYS_ABILITY_ID);
528         saStatusChangeListener_ = nullptr;
529     }
530 }
531 
UpdateMode(int64_t period, int64_t phase, int64_t referenceTime)532 VsyncError VSyncGenerator::UpdateMode(int64_t period, int64_t phase, int64_t referenceTime)
533 {
534     if (IsPcType() && IsPCRefreshRateLock60()) {
535         period = REFRESH_PERIOD;
536     }
537     std::lock_guard<std::mutex> locker(mutex_);
538     RS_TRACE_NAME_FMT("UpdateMode, period:%ld, phase:%ld, referenceTime:%ld, referenceTimeOffsetPulseNum_:%d",
539         period, phase, referenceTime, referenceTimeOffsetPulseNum_);
540     if (period < 0 || referenceTime < 0) {
541         VLOGE("wrong parameter, period:" VPUBI64 ", referenceTime:" VPUBI64, period, referenceTime);
542         return VSYNC_ERROR_INVALID_ARGUMENTS;
543     }
544     phase_ = phase;
545     if (period != 0) {
546         UpdatePeriodLocked(period);
547     }
548     UpdateReferenceTimeLocked(referenceTime);
549     startRefresh_ = false;
550     con_.notify_all();
551     return VSYNC_ERROR_OK;
552 }
553 
AddListener(int64_t phase, const sptr<OHOS::Rosen::VSyncGenerator::Callback>& cb)554 VsyncError VSyncGenerator::AddListener(int64_t phase, const sptr<OHOS::Rosen::VSyncGenerator::Callback>& cb)
555 {
556     ScopedBytrace func("AddListener");
557     std::lock_guard<std::mutex> locker(mutex_);
558     if (cb == nullptr) {
559         return VSYNC_ERROR_INVALID_ARGUMENTS;
560     }
561     Listener listener;
562     listener.phase_ = phase;
563     listener.callback_ = cb;
564     listener.lastTime_ = SystemTime() - period_ + phase_;
565 
566     listeners_.push_back(listener);
567 
568     size_t i = 0;
569     for (; i < listenersRecord_.size(); i++) {
570         if (listener.callback_ == listenersRecord_[i].callback_) {
571             break;
572         }
573     }
574     if (i == listenersRecord_.size()) {
575         listenersRecord_.push_back(listener);
576     }
577     con_.notify_all();
578     waitForTimeoutCon_.notify_all();
579     return VSYNC_ERROR_OK;
580 }
581 
JudgeRefreshRateLocked(int64_t period)582 uint32_t VSyncGenerator::JudgeRefreshRateLocked(int64_t period)
583 {
584     if (period <= 0) {
585         return 0;
586     }
587     int32_t actualRefreshRate = round(1.0/((double)period/1000000000.0)); // 1.0s == 1000000000.0ns
588     if (actualRefreshRate == 0) { // actualRefreshRate is greater than 0
589         return 0;
590     }
591     int32_t refreshRate = actualRefreshRate;
592     int32_t diff = 0;
593     // 在actualRefreshRate附近找一个能被vsyncMaxRefreshRate_整除的刷新率作为训练pulse的参考刷新率
594     // refreshRate is greater than 0, and the value is in following range:
595     // [max(1, actualRefreshRate - MAX_REFRESHRATE_DEVIATION), actualRefreshRate + MAX_REFRESHRATE_DEVIATION]
596     while ((abs(refreshRate - actualRefreshRate) < MAX_REFRESHRATE_DEVIATION) &&
597            (vsyncMaxRefreshRate_ % static_cast<uint32_t>(refreshRate) != 0)) {
598         if (diff < 0) {
599             diff = -diff;
600         } else {
601             diff = -diff - 1;
602         }
603         refreshRate = actualRefreshRate + diff;
604     }
605     if (vsyncMaxRefreshRate_ % static_cast<uint32_t>(refreshRate) != 0) {
606         VLOGE("Not Support this refresh rate: %{public}d, update pulse failed.", actualRefreshRate);
607         return 0;
608     }
609     pulse_ = period / static_cast<int64_t>(vsyncMaxRefreshRate_ / static_cast<uint32_t>(refreshRate));
610     return static_cast<uint32_t>(refreshRate);
611 }
612 
SetExpectNextVsyncTimeInternal(int64_t expectNextVsyncTime)613 VsyncError VSyncGenerator::SetExpectNextVsyncTimeInternal(int64_t expectNextVsyncTime)
614 {
615     if (expectNextVsyncTime <= 0) {
616         return VSYNC_ERROR_OK;
617     }
618     auto now = SystemTime();
619     int64_t expectTime = 0;
620     if (expectNextVsyncTime - referenceTime_ > 0) {
621         if (((expectNextVsyncTime - referenceTime_) % pulse_) < (pulse_ / 2)) { // check with 1/2 pulse
622             expectTime = ((expectNextVsyncTime - referenceTime_) / pulse_) * pulse_ + referenceTime_;
623         } else {
624             expectTime = ((expectNextVsyncTime - referenceTime_) / pulse_ + 1) * pulse_ + referenceTime_;
625         }
626     }
627     if (expectTime == 0 || expectTime - now > 100000000) { // 100ms == 100000000ns
628         RS_TRACE_NAME_FMT("SetExpectNextVsyncTime Failed, expectTime:%ld, now:%ld, expectNextVsyncTime:%ld,"
629             " referenceTime_:%ld", expectTime, now, expectNextVsyncTime, referenceTime_);
630         return VSYNC_ERROR_INVALID_ARGUMENTS;
631     }
632     expectNextVsyncTime_ = expectTime;
633     RS_TRACE_NAME_FMT("expectNextVsyncTime:%ld, expectNextVsyncTime_:%ld, diff:%ld", expectNextVsyncTime,
634         expectNextVsyncTime_, (expectNextVsyncTime_ - expectNextVsyncTime));
635     return VSYNC_ERROR_OK;
636 }
637 
ChangeGeneratorRefreshRateModel(const ListenerRefreshRateData &listenerRefreshRates, const ListenerPhaseOffsetData &listenerPhaseOffset, uint32_t generatorRefreshRate, int64_t &rsVsyncCount, int64_t expectNextVsyncTime)638 VsyncError VSyncGenerator::ChangeGeneratorRefreshRateModel(const ListenerRefreshRateData &listenerRefreshRates,
639                                                            const ListenerPhaseOffsetData &listenerPhaseOffset,
640                                                            uint32_t generatorRefreshRate,
641                                                            int64_t &rsVsyncCount,
642                                                            int64_t expectNextVsyncTime)
643 {
644     if (rsVSyncDistributor_ != nullptr) {
645         rsVsyncCount = rsVSyncDistributor_->GetVsyncCount();
646     }
647     RS_TRACE_NAME_FMT("ChangeGeneratorRefreshRateModel:%u, phaseByPulseNum:%d, expectNextVsyncTime:%ld",
648         generatorRefreshRate, listenerPhaseOffset.phaseByPulseNum, expectNextVsyncTime);
649     for (std::pair<uint64_t, uint32_t> rateVec : listenerRefreshRates.refreshRates) {
650         uint64_t linkerId = rateVec.first;
651         uint32_t refreshrate = rateVec.second;
652         RS_TRACE_NAME_FMT("linkerId:%ld, refreshrate:%ld", linkerId, refreshrate);
653     }
654     std::lock_guard<std::mutex> locker(mutex_);
655     if ((vsyncMode_ != VSYNC_MODE_LTPO) && (pendingVsyncMode_ != VSYNC_MODE_LTPO)) {
656         ScopedBytrace trace("it's not ltpo mode.");
657         return VSYNC_ERROR_NOT_SUPPORT;
658     }
659     if (pulse_ == 0) {
660         ScopedBytrace trace("pulse is not ready!!!");
661         VLOGE("pulse is not ready!!!");
662         return VSYNC_ERROR_API_FAILED;
663     }
664 
665     VsyncError ret = SetExpectNextVsyncTimeInternal(expectNextVsyncTime);
666 
667     if ((generatorRefreshRate <= 0 || (vsyncMaxRefreshRate_ % generatorRefreshRate != 0))) {
668         RS_TRACE_NAME_FMT("Not support this refresh rate: %u", generatorRefreshRate);
669         VLOGE("Not support this refresh rate: %{public}u", generatorRefreshRate);
670         return VSYNC_ERROR_NOT_SUPPORT;
671     }
672 
673     if (changingRefreshRates_.cb == nullptr) {
674         changingRefreshRates_ = listenerRefreshRates;
675     } else {
676         UpdateChangeRefreshRatesLocked(listenerRefreshRates);
677     }
678     needChangeRefreshRates_ = true;
679 
680     changingPhaseOffset_ = listenerPhaseOffset;
681     needChangePhaseOffset_ = true;
682 
683     if (generatorRefreshRate != currRefreshRate_) {
684         changingGeneratorRefreshRate_ = generatorRefreshRate;
685         needChangeGeneratorRefreshRate_ = true;
686     } else {
687         RS_TRACE_NAME_FMT("refreshRateNotChanged, generatorRefreshRate:%u, currRefreshRate_:%u",
688             generatorRefreshRate, currRefreshRate_);
689     }
690 
691     waitForTimeoutCon_.notify_all();
692     return ret;
693 }
694 
UpdateChangeRefreshRatesLocked(const ListenerRefreshRateData &listenerRefreshRates)695 void VSyncGenerator::UpdateChangeRefreshRatesLocked(const ListenerRefreshRateData &listenerRefreshRates)
696 {
697     for (auto refreshRate : listenerRefreshRates.refreshRates) {
698         bool found = false;
699         for (auto it = changingRefreshRates_.refreshRates.begin();
700              it != changingRefreshRates_.refreshRates.end(); it++) {
701             if ((*it).first == refreshRate.first) { // first is linkerId
702                 (*it).second = refreshRate.second; // second is refreshRate
703                 found = true;
704                 break;
705             }
706         }
707         if (!found) {
708             changingRefreshRates_.refreshRates.push_back(refreshRate);
709         }
710     }
711 }
712 
GetVSyncPulse()713 int64_t VSyncGenerator::GetVSyncPulse()
714 {
715     std::lock_guard<std::mutex> locker(mutex_);
716     return pulse_;
717 }
718 
SetVSyncMode(VSyncMode vsyncMode)719 VsyncError VSyncGenerator::SetVSyncMode(VSyncMode vsyncMode)
720 {
721     RS_TRACE_NAME_FMT("SetVSyncMode:%d", vsyncMode);
722     std::lock_guard<std::mutex> locker(mutex_);
723     pendingVsyncMode_ = vsyncMode;
724     return VSYNC_ERROR_OK;
725 }
726 
GetVSyncMode()727 VSyncMode VSyncGenerator::GetVSyncMode()
728 {
729     std::lock_guard<std::mutex> locker(mutex_);
730     return vsyncMode_;
731 }
732 
SetVSyncPhaseByPulseNum(int32_t phaseByPulseNum)733 VsyncError VSyncGenerator::SetVSyncPhaseByPulseNum(int32_t phaseByPulseNum)
734 {
735     std::lock_guard<std::mutex> locker(mutex_);
736     referenceTimeOffsetPulseNum_ = phaseByPulseNum;
737     defaultReferenceTimeOffsetPulseNum_ = phaseByPulseNum;
738     return VSYNC_ERROR_OK;
739 }
740 
GetVSyncMaxRefreshRate()741 uint32_t VSyncGenerator::GetVSyncMaxRefreshRate()
742 {
743     return vsyncMaxRefreshRate_;
744 }
745 
SetVSyncMaxRefreshRate(uint32_t refreshRate)746 VsyncError VSyncGenerator::SetVSyncMaxRefreshRate(uint32_t refreshRate)
747 {
748     std::lock_guard<std::mutex> locker(mutex_);
749     if (refreshRate < VSYNC_MAX_REFRESHRATE_RANGE_MIN ||
750         refreshRate > VSYNC_MAX_REFRESHRATE_RANGE_MAX) {
751         VLOGE("Not support max refresh rate: %{public}u", refreshRate);
752         return VSYNC_ERROR_INVALID_ARGUMENTS;
753     }
754     vsyncMaxRefreshRate_ = refreshRate;
755     return VSYNC_ERROR_OK;
756 }
757 
SetReferenceTimeOffset(int32_t offsetByPulseNum)758 VsyncError VSyncGenerator::SetReferenceTimeOffset(int32_t offsetByPulseNum)
759 {
760     std::lock_guard<std::mutex> locker(mutex_);
761     referenceTimeOffsetPulseNum_ = offsetByPulseNum;
762     return VSYNC_ERROR_OK;
763 }
764 
StartRefresh()765 VsyncError VSyncGenerator::StartRefresh()
766 {
767     RS_TRACE_NAME("StartRefresh");
768     std::lock_guard<std::mutex> lock(mutex_);
769     startRefresh_ = true;
770     referenceTimeOffsetPulseNum_ = defaultReferenceTimeOffsetPulseNum_;
771     return VSYNC_ERROR_OK;
772 }
773 
SetRSDistributor(sptr<VSyncDistributor> &rsVSyncDistributor)774 void VSyncGenerator::SetRSDistributor(sptr<VSyncDistributor> &rsVSyncDistributor)
775 {
776     std::lock_guard<std::mutex> lock(mutex_);
777     rsVSyncDistributor_ = rsVSyncDistributor;
778 }
779 
PeriodCheckLocked(int64_t hardwareVsyncInterval)780 void VSyncGenerator::PeriodCheckLocked(int64_t hardwareVsyncInterval)
781 {
782     if (lastPeriod_ == period_) {
783         if (abs(hardwareVsyncInterval - period_) > PERIOD_CHECK_THRESHOLD) {
784             // if software period not changed, and hardwareVsyncInterval,
785             // and software period is not the same, accumulate counter
786             periodCheckCounter_++;
787             RS_TRACE_NAME_FMT("CounterAccumulated, lastPeriod_:%ld, period_:%ld, hardwareVsyncInterval:%ld,"
788                 " periodCheckCounter_:%d", lastPeriod_, period_, hardwareVsyncInterval, periodCheckCounter_);
789         }
790     } else {
791         // if period changed, record this period as lastPeriod_ and clear periodCheckCounter_
792         lastPeriod_ = period_;
793         periodCheckCounter_ = 0;
794         RS_TRACE_NAME("periodCheckCounter_ = 0");
795     }
796     // exit frameRateChanging status when the frame rate is inconsistent for 10 consecutive times.
797     if (periodCheckCounter_ > 10) {
798         RS_TRACE_NAME_FMT("samePeriodCounter ERROR, period_:%ld, hardwareVsyncInterval:%ld, pendingReferenceTime_:%ld"
799             ", referenceTime_:%ld, referenceTimeDiff:%ld", period_, hardwareVsyncInterval, pendingReferenceTime_,
800             referenceTime_, abs(pendingReferenceTime_ - referenceTime_));
801         VLOGE("samePeriodCounter ERROR, period_:" VPUBI64 ", hardwareVsyncInterval:" VPUBI64
802             ", pendingReferenceTime_:" VPUBI64 ", referenceTime_:" VPUBI64 ", referenceTimeDiff:" VPUBI64,
803             period_, hardwareVsyncInterval, pendingReferenceTime_, referenceTime_,
804             abs(pendingReferenceTime_ - referenceTime_));
805         // end the frameRateChanging status
806         frameRateChanging_ = false;
807         ScopedBytrace forceEnd("frameRateChanging_ = false, forceEnd");
808     }
809 }
810 
SetAppDistributor(sptr<VSyncDistributor> &appVSyncDistributor)811 void VSyncGenerator::SetAppDistributor(sptr<VSyncDistributor> &appVSyncDistributor)
812 {
813     std::lock_guard<std::mutex> lock(mutex_);
814     appVSyncDistributor_ = appVSyncDistributor;
815 }
816 
CalculateReferenceTimeOffsetPulseNumLocked(int64_t referenceTime)817 void VSyncGenerator::CalculateReferenceTimeOffsetPulseNumLocked(int64_t referenceTime)
818 {
819     int64_t actualOffset = referenceTime - pendingReferenceTime_;
820     int32_t actualOffsetPulseNum = round((double)actualOffset/(double)pulse_);
821     if (startRefresh_ || (defaultReferenceTimeOffsetPulseNum_ == 0)) {
822         referenceTimeOffsetPulseNum_ = defaultReferenceTimeOffsetPulseNum_;
823     } else {
824         referenceTimeOffsetPulseNum_ = std::max(actualOffsetPulseNum, defaultReferenceTimeOffsetPulseNum_);
825     }
826     RS_TRACE_NAME_FMT("UpdateMode, referenceTime:%ld, actualOffsetPulseNum:%d, referenceTimeOffsetPulseNum_:%d"
827         ", startRefresh_:%d, period:%ld", referenceTime, actualOffsetPulseNum, referenceTimeOffsetPulseNum_,
828         startRefresh_, pendingPeriod_);
829 }
830 
CheckAndUpdateReferenceTime(int64_t hardwareVsyncInterval, int64_t referenceTime)831 VsyncError VSyncGenerator::CheckAndUpdateReferenceTime(int64_t hardwareVsyncInterval, int64_t referenceTime)
832 {
833     if (hardwareVsyncInterval < 0 || referenceTime < 0) {
834         VLOGE("wrong parameter, hardwareVsyncInterval:" VPUBI64 ", referenceTime:" VPUBI64,
835                 hardwareVsyncInterval, referenceTime);
836         return VSYNC_ERROR_INVALID_ARGUMENTS;
837     }
838     std::lock_guard<std::mutex> locker(mutex_);
839     if ((pendingPeriod_ <= 0 && targetPeriod_ <= 0) || pulse_ == 0) {
840         frameRateChanging_ = false;
841         VLOGE("[%{public}s] Failed, pendingPeriod_:" VPUBI64 ", targetPeriod_:" VPUBI64 ", pulse_:" VPUBI64,
842             __func__, pendingPeriod_, targetPeriod_, pulse_);
843         return VSYNC_ERROR_API_FAILED;
844     }
845 
846     PeriodCheckLocked(hardwareVsyncInterval);
847 
848     if (((abs(hardwareVsyncInterval - pendingPeriod_) < PERIOD_CHECK_THRESHOLD) &&
849         (abs(hardwareVsyncInterval - targetPeriod_) < PERIOD_CHECK_THRESHOLD || targetPeriod_ == 0))) {
850         // framerate has changed
851         frameRateChanging_ = false;
852         ScopedBytrace changeEnd("frameRateChanging_ = false");
853         CalculateReferenceTimeOffsetPulseNumLocked(referenceTime);
854         UpdateReferenceTimeLocked(referenceTime);
855         bool needNotify = true;
856         uint32_t periodRefreshRate = CalculateRefreshRate(period_);
857         uint32_t pendingPeriodRefreshRate = CalculateRefreshRate(pendingPeriod_);
858         // 120hz, 90hz, 60hz
859         if (((periodRefreshRate == 120) || (periodRefreshRate == 90)) && (pendingPeriodRefreshRate == 60)) {
860             needNotify = false;
861         }
862         if ((periodRefreshRate != 0) && (periodRefreshRate == pendingPeriodRefreshRate)) {
863             RS_TRACE_NAME_FMT("period not changed, period:%ld", period_);
864             needNotify = false;
865         } else {
866             UpdatePeriodLocked(pendingPeriod_);
867         }
868         if (needNotify) {
869             waitForTimeoutCon_.notify_all();
870         }
871         pendingPeriod_ = 0;
872         targetPeriod_ = 0;
873         startRefresh_ = false;
874     }
875     return VSYNC_ERROR_OK;
876 }
877 
RemoveListener(const sptr<OHOS::Rosen::VSyncGenerator::Callback>& cb)878 VsyncError VSyncGenerator::RemoveListener(const sptr<OHOS::Rosen::VSyncGenerator::Callback>& cb)
879 {
880     ScopedBytrace func("RemoveListener");
881     std::lock_guard<std::mutex> locker(mutex_);
882     if (cb == nullptr) {
883         return VSYNC_ERROR_INVALID_ARGUMENTS;
884     }
885     bool removeFlag = false;
886     auto it = listeners_.begin();
887     for (; it < listeners_.end(); it++) {
888         if (it->callback_ == cb) {
889             listeners_.erase(it);
890             removeFlag = true;
891             break;
892         }
893     }
894     if (!removeFlag) {
895         return VSYNC_ERROR_INVALID_ARGUMENTS;
896     }
897     return VSYNC_ERROR_OK;
898 }
899 
ChangePhaseOffset(const sptr<OHOS::Rosen::VSyncGenerator::Callback>& cb, int64_t offset)900 VsyncError VSyncGenerator::ChangePhaseOffset(const sptr<OHOS::Rosen::VSyncGenerator::Callback>& cb, int64_t offset)
901 {
902     std::lock_guard<std::mutex> locker(mutex_);
903     if (cb == nullptr) {
904         return VSYNC_ERROR_INVALID_ARGUMENTS;
905     }
906     auto it = listeners_.begin();
907     for (; it < listeners_.end(); it++) {
908         if (it->callback_ == cb) {
909             break;
910         }
911     }
912     if (it != listeners_.end()) {
913         it->phase_ = offset;
914     } else {
915         return VSYNC_ERROR_INVALID_OPERATING;
916     }
917     return VSYNC_ERROR_OK;
918 }
919 
IsEnable()920 bool VSyncGenerator::IsEnable()
921 {
922     std::lock_guard<std::mutex> locker(mutex_);
923     return period_ > 0;
924 }
925 
GetFrameRateChaingStatus()926 bool VSyncGenerator::GetFrameRateChaingStatus()
927 {
928     std::lock_guard<std::mutex> locker(mutex_);
929     return frameRateChanging_;
930 }
931 
SetFrameRateChangingStatus(bool frameRateChanging)932 void VSyncGenerator::SetFrameRateChangingStatus(bool frameRateChanging)
933 {
934     std::lock_guard<std::mutex> locker(mutex_);
935     frameRateChanging_ = frameRateChanging;
936 }
937 
SetPendingMode(int64_t period, int64_t timestamp)938 void VSyncGenerator::SetPendingMode(int64_t period, int64_t timestamp)
939 {
940     if (period <= 0) {
941         return;
942     }
943     std::lock_guard<std::mutex> lock(mutex_);
944     pendingPeriod_ = period;
945     pendingReferenceTime_ = timestamp;
946     if (rsVSyncDistributor_ != nullptr) {
947         rsVSyncDistributor_->UpdatePendingReferenceTime(pendingReferenceTime_);
948     }
949 }
950 
Dump(std::string &result)951 void VSyncGenerator::Dump(std::string &result)
952 {
953     std::unique_lock<std::mutex> lock(mutex_);
954     result.append("\n-- VSyncGenerator --");
955     result += "\nperiod:" + std::to_string(period_);
956     result += "\nphase:" + std::to_string(phase_);
957     result += "\nreferenceTime:" + std::to_string(referenceTime_);
958     result += "\nvsyncMode:" + std::to_string(vsyncMode_);
959     result += "\nperiodCheckCounter_:" + std::to_string(periodCheckCounter_);
960 }
961 } // namespace impl
CreateVSyncGenerator()962 sptr<VSyncGenerator> CreateVSyncGenerator()
963 {
964     return impl::VSyncGenerator::GetInstance();
965 }
966 
DestroyVSyncGenerator()967 void DestroyVSyncGenerator()
968 {
969     impl::VSyncGenerator::DeleteInstance();
970 }
971 }
972 }
973