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