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