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, ¶m);
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