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