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