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
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