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_distributor.h"
17 #include <chrono>
18 #include <condition_variable>
19 #include <algorithm>
20 #include <cstdint>
21 #include <mutex>
22 #include <sched.h>
23 #include <sys/resource.h>
24 #include <scoped_bytrace.h>
25 #include <hitrace_meter.h>
26 #include "vsync_log.h"
27 #include "vsync_type.h"
28 #include "vsync_generator.h"
29 #include <rs_trace.h>
30 #include "scoped_trace_fmt.h"
31
32 #ifdef COMPOSER_SCHED_ENABLE
33 #include "if_system_ability_manager.h"
34 #include <iservice_registry.h>
35 #include "system_ability_definition.h"
36 #endif
37
38 namespace OHOS {
39 namespace Rosen {
40 namespace {
41 constexpr int32_t SOFT_VSYNC_PERIOD = 16;
42 constexpr int32_t ERRNO_EAGAIN = -1;
43 constexpr int32_t ERRNO_OTHER = -2;
44 constexpr int32_t THREAD_PRIORTY = -6;
45 constexpr int32_t SCHED_PRIORITY = 2;
46 constexpr int32_t DEFAULT_VSYNC_RATE = 1;
47 constexpr uint32_t SOCKET_CHANNEL_SIZE = 1024;
48 constexpr int32_t VSYNC_CONNECTION_MAX_SIZE = 256;
49 }
50
VSyncConnectionDeathRecipient(wptr<VSyncConnection> conn)51 VSyncConnection::VSyncConnectionDeathRecipient::VSyncConnectionDeathRecipient(
52 wptr<VSyncConnection> conn) : conn_(conn)
53 {
54 }
55
OnRemoteDied(const wptr<IRemoteObject> & token)56 void VSyncConnection::VSyncConnectionDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& token)
57 {
58 auto tokenSptr = token.promote();
59 if (tokenSptr == nullptr) {
60 VLOGW("%{public}s: can't promote remote object.", __func__);
61 return;
62 }
63 auto vsyncConn = conn_.promote();
64 if (vsyncConn == nullptr) {
65 VLOGW("%{public}s: VSyncConnection was dead, do nothing.", __func__);
66 return;
67 }
68 if (vsyncConn->token_ != tokenSptr) {
69 VLOGI("%{public}s: token doesn't match, ignore it.", __func__);
70 return;
71 }
72 VLOGD("%{public}s: clear socketPair, conn name:%{public}s.", __func__, vsyncConn->info_.name_.c_str());
73 VsyncError ret = vsyncConn->Destroy();
74 if (ret != VSYNC_ERROR_OK) {
75 VLOGE("vsync connection clearAll failed!");
76 }
77 }
78
VSyncConnection(const sptr<VSyncDistributor> & distributor,std::string name,const sptr<IRemoteObject> & token,uint64_t id,uint64_t windowNodeId)79 VSyncConnection::VSyncConnection(
80 const sptr<VSyncDistributor>& distributor,
81 std::string name,
82 const sptr<IRemoteObject>& token,
83 uint64_t id,
84 uint64_t windowNodeId)
85 : rate_(-1),
86 info_(name),
87 id_(id),
88 windowNodeId_(windowNodeId),
89 vsyncConnDeathRecipient_(new VSyncConnectionDeathRecipient(this)),
90 token_(token),
91 distributor_(distributor)
92 {
93 socketPair_ = new LocalSocketPair();
94 int32_t err = socketPair_->CreateChannel(SOCKET_CHANNEL_SIZE, SOCKET_CHANNEL_SIZE);
95 if (err != 0) {
96 RS_TRACE_NAME_FMT("Create socket channel failed, errno = %d", errno);
97 }
98 if (token_ != nullptr) {
99 token_->AddDeathRecipient(vsyncConnDeathRecipient_);
100 }
101 proxyPid_ = GetCallingPid();
102 isDead_ = false;
103 }
104
~VSyncConnection()105 VSyncConnection::~VSyncConnection()
106 {
107 if ((token_ != nullptr) && (vsyncConnDeathRecipient_ != nullptr)) {
108 token_->RemoveDeathRecipient(vsyncConnDeathRecipient_);
109 }
110 }
111
RequestNextVSync()112 VsyncError VSyncConnection::RequestNextVSync()
113 {
114 static const std::string DEFAULT_REQUEST = "unknown";
115 return RequestNextVSync(DEFAULT_REQUEST, 0);
116 }
117
RequestNextVSync(const std::string & fromWhom,int64_t lastVSyncTS)118 VsyncError VSyncConnection::RequestNextVSync(const std::string &fromWhom, int64_t lastVSyncTS)
119 {
120 sptr<VSyncDistributor> distributor;
121 {
122 std::unique_lock<std::mutex> locker(mutex_);
123 if (isDead_) {
124 VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
125 return VSYNC_ERROR_API_FAILED;
126 }
127 if (distributor_ == nullptr) {
128 return VSYNC_ERROR_NULLPTR;
129 }
130 distributor = distributor_.promote();
131 if (distributor == nullptr) {
132 return VSYNC_ERROR_NULLPTR;
133 }
134 if (isFirstRequestVsync_) {
135 isFirstRequestVsync_ = false;
136 VLOGI("First vsync is requested, name: %{public}s", info_.name_.c_str());
137 }
138 }
139 return distributor->RequestNextVSync(this, fromWhom, lastVSyncTS);
140 }
141
GetReceiveFd(int32_t & fd)142 VsyncError VSyncConnection::GetReceiveFd(int32_t &fd)
143 {
144 std::unique_lock<std::mutex> locker(mutex_);
145 if (isDead_) {
146 VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
147 return VSYNC_ERROR_API_FAILED;
148 }
149 fd = socketPair_->GetReceiveDataFd();
150 if (fd <= 0) {
151 VLOGE("%{public}s socketPair invalid fd:%{public}d.", __func__, fd);
152 return VSYNC_ERROR_API_FAILED;
153 }
154 return VSYNC_ERROR_OK;
155 }
156
PostEvent(int64_t now,int64_t period,int64_t vsyncCount)157 int32_t VSyncConnection::PostEvent(int64_t now, int64_t period, int64_t vsyncCount)
158 {
159 sptr<LocalSocketPair> socketPair;
160 {
161 std::unique_lock<std::mutex> locker(mutex_);
162 if (isDead_) {
163 RS_TRACE_NAME_FMT("Vsync Client Connection is dead, conn: %s", info_.name_.c_str());
164 VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
165 return ERRNO_OTHER;
166 }
167 socketPair = socketPair_;
168 }
169 if (socketPair == nullptr) {
170 RS_TRACE_NAME_FMT("socketPair is null, conn: %s", info_.name_.c_str());
171 return ERRNO_OTHER;
172 }
173
174 std::unique_lock<std::mutex> lockerPostEvent(postEventMutex_);
175 RS_TRACE_NAME_FMT("SendVsyncTo conn: %s, now:%ld, refreshRate:%d", info_.name_.c_str(), now, refreshRate_);
176 // 3 is array size.
177 int64_t data[3];
178 data[0] = now;
179 // 1, 2: index of array data.
180 data[1] = period;
181 data[2] = vsyncCount;
182 if (isFirstSendVsync_) {
183 isFirstSendVsync_ = false;
184 VLOGI("First vsync has send to : %{public}s", info_.name_.c_str());
185 }
186 int32_t ret = socketPair->SendData(data, sizeof(data));
187 if (ret == ERRNO_EAGAIN) {
188 RS_TRACE_NAME("remove the earlies data and SendData again.");
189 VLOGW("vsync signal is not processed in time, please check pid:%{public}d", proxyPid_);
190 int64_t receiveData[3];
191 socketPair->ReceiveData(receiveData, sizeof(receiveData));
192 ret = socketPair->SendData(data, sizeof(data));
193 }
194 if (ret > -1) {
195 ScopedDebugTrace successful("successful");
196 info_.postVSyncCount_++;
197 if (gcNotifyTask_ != nullptr) {
198 gcNotifyTask_(false);
199 }
200 } else {
201 ScopedBytrace failed("failed");
202 }
203 return ret;
204 }
205
SetVSyncRate(int32_t rate)206 VsyncError VSyncConnection::SetVSyncRate(int32_t rate)
207 {
208 std::unique_lock<std::mutex> locker(mutex_);
209 if (isDead_) {
210 VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
211 return VSYNC_ERROR_API_FAILED;
212 }
213 if (distributor_ == nullptr) {
214 return VSYNC_ERROR_NULLPTR;
215 }
216 const sptr<VSyncDistributor> distributor = distributor_.promote();
217 if (distributor == nullptr) {
218 return VSYNC_ERROR_NULLPTR;
219 }
220 return distributor->SetVSyncRate(rate, this);
221 }
222
CleanAllLocked()223 VsyncError VSyncConnection::CleanAllLocked()
224 {
225 socketPair_ = nullptr;
226 const sptr<VSyncDistributor> distributor = distributor_.promote();
227 if (distributor == nullptr) {
228 return VSYNC_ERROR_OK;
229 }
230 VsyncError ret = distributor->RemoveConnection(this);
231 isDead_ = true;
232 return ret;
233 }
234
Destroy()235 VsyncError VSyncConnection::Destroy()
236 {
237 std::unique_lock<std::mutex> locker(mutex_);
238 return CleanAllLocked();
239 }
240
SetUiDvsyncSwitch(bool dvsyncSwitch)241 VsyncError VSyncConnection::SetUiDvsyncSwitch(bool dvsyncSwitch)
242 {
243 sptr<VSyncDistributor> distributor;
244 {
245 std::unique_lock<std::mutex> locker(mutex_);
246 if (isDead_) {
247 VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
248 return VSYNC_ERROR_API_FAILED;
249 }
250 if (distributor_ == nullptr) {
251 return VSYNC_ERROR_NULLPTR;
252 }
253 distributor = distributor_.promote();
254 if (distributor == nullptr) {
255 return VSYNC_ERROR_NULLPTR;
256 }
257 }
258 return distributor->SetUiDvsyncSwitch(dvsyncSwitch, this);
259 }
260
SetNativeDVSyncSwitch(bool dvsyncSwitch)261 VsyncError VSyncConnection::SetNativeDVSyncSwitch(bool dvsyncSwitch)
262 {
263 sptr<VSyncDistributor> distributor;
264 {
265 std::unique_lock<std::mutex> locker(mutex_);
266 if (isDead_) {
267 VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
268 return VSYNC_ERROR_API_FAILED;
269 }
270 if (distributor_ == nullptr) {
271 return VSYNC_ERROR_NULLPTR;
272 }
273 distributor = distributor_.promote();
274 if (distributor == nullptr) {
275 return VSYNC_ERROR_NULLPTR;
276 }
277 }
278 return distributor->SetNativeDVSyncSwitch(dvsyncSwitch, this);
279 }
280
SetUiDvsyncConfig(int32_t bufferCount)281 VsyncError VSyncConnection::SetUiDvsyncConfig(int32_t bufferCount)
282 {
283 sptr<VSyncDistributor> distributor;
284 {
285 std::unique_lock<std::mutex> locker(mutex_);
286 if (isDead_) {
287 VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
288 return VSYNC_ERROR_API_FAILED;
289 }
290 if (distributor_ == nullptr) {
291 return VSYNC_ERROR_NULLPTR;
292 }
293 distributor = distributor_.promote();
294 if (distributor == nullptr) {
295 return VSYNC_ERROR_NULLPTR;
296 }
297 }
298 return distributor->SetUiDvsyncConfig(bufferCount);
299 }
300
VSyncDistributor(sptr<VSyncController> controller,std::string name)301 VSyncDistributor::VSyncDistributor(sptr<VSyncController> controller, std::string name)
302 : controller_(controller), mutex_(), con_(), connections_(),
303 event_(), vsyncEnabled_(false), name_(name)
304 {
305 static const std::string DEFAULT_RS_NAME = "rs";
306 if (name == DEFAULT_RS_NAME) {
307 isRs_ = true;
308 }
309 #if defined(RS_ENABLE_DVSYNC)
310 dvsync_ = new DVsync(isRs_);
311 if (dvsync_->IsFeatureEnabled()) {
312 vsyncThreadRunning_ = true;
313 threadLoop_ = std::thread([this] { this->ThreadMain(); });
314 std::string threadName = "DVSync-" + name;
315 pthread_setname_np(threadLoop_.native_handle(), threadName.c_str());
316 }
317 #endif
318 }
319
~VSyncDistributor()320 VSyncDistributor::~VSyncDistributor()
321 {
322 #if defined(RS_ENABLE_DVSYNC)
323 if (dvsync_->IsFeatureEnabled()) {
324 {
325 std::unique_lock<std::mutex> locker(mutex_);
326 vsyncThreadRunning_ = false;
327 }
328 if (threadLoop_.joinable()) {
329 {
330 std::unique_lock<std::mutex> locker(mutex_);
331 dvsync_->RNVNotify();
332 }
333 con_.notify_all();
334 threadLoop_.join();
335 }
336 }
337 #endif
338 }
339
AddConnection(const sptr<VSyncConnection> & connection,uint64_t windowNodeId)340 VsyncError VSyncDistributor::AddConnection(const sptr<VSyncConnection>& connection, uint64_t windowNodeId)
341 {
342 if (connection == nullptr) {
343 return VSYNC_ERROR_NULLPTR;
344 }
345 std::lock_guard<std::mutex> locker(mutex_);
346 int32_t proxyPid = connection->proxyPid_;
347 if (connectionCounter_[proxyPid] > VSYNC_CONNECTION_MAX_SIZE) {
348 VLOGE("You [%{public}d] have created too many vsync connection, please check!!!", proxyPid);
349 return VSYNC_ERROR_API_FAILED;
350 }
351 auto it = std::find(connections_.begin(), connections_.end(), connection);
352 if (it != connections_.end()) {
353 return VSYNC_ERROR_INVALID_ARGUMENTS;
354 }
355 RS_TRACE_NAME_FMT("Add VSyncConnection: %s", connection->info_.name_.c_str());
356 connections_.push_back(connection);
357 connectionCounter_[proxyPid]++;
358 if (windowNodeId != 0) {
359 connectionsMap_[windowNodeId].push_back(connection);
360 } else {
361 uint32_t tmpPid;
362 if (QosGetPidByName(connection->info_.name_, tmpPid) == VSYNC_ERROR_OK) {
363 connectionsMap_[tmpPid].push_back(connection);
364 }
365 }
366
367 return VSYNC_ERROR_OK;
368 }
369
RemoveConnection(const sptr<VSyncConnection> & connection)370 VsyncError VSyncDistributor::RemoveConnection(const sptr<VSyncConnection>& connection)
371 {
372 if (connection == nullptr) {
373 return VSYNC_ERROR_NULLPTR;
374 }
375 std::lock_guard<std::mutex> locker(mutex_);
376 int32_t proxyPid = connection->proxyPid_;
377 auto it = std::find(connections_.begin(), connections_.end(), connection);
378 if (it == connections_.end()) {
379 return VSYNC_ERROR_INVALID_ARGUMENTS;
380 }
381 RS_TRACE_NAME_FMT("Remove VSyncConnection: %s", connection->info_.name_.c_str());
382 connections_.erase(it);
383 connectionCounter_[proxyPid]--;
384 if (connectionCounter_[proxyPid] == 0) {
385 connectionCounter_.erase(proxyPid);
386 }
387 connectionsMap_.erase(connection->windowNodeId_);
388 uint32_t tmpPid;
389 if (QosGetPidByName(connection->info_.name_, tmpPid) == VSYNC_ERROR_OK) {
390 auto iter = connectionsMap_.find(tmpPid);
391 if (iter == connectionsMap_.end()) {
392 return VSYNC_ERROR_OK;
393 }
394 auto connIter = find(iter->second.begin(), iter->second.end(), connection);
395 if (connIter != iter->second.end()) {
396 iter->second.erase(connIter);
397 }
398 if (iter->second.empty()) {
399 connectionsMap_.erase(iter);
400 }
401 }
402 return VSYNC_ERROR_OK;
403 }
404
WaitForVsyncOrRequest(std::unique_lock<std::mutex> & locker)405 void VSyncDistributor::WaitForVsyncOrRequest(std::unique_lock<std::mutex> &locker)
406 {
407 if (!vsyncThreadRunning_) {
408 return;
409 }
410
411 // before con_ wait, notify the rnv_con.
412 #if defined(RS_ENABLE_DVSYNC)
413 dvsync_->RNVNotify();
414 if (!isRs_ && IsDVsyncOn()) {
415 con_.wait_for(locker, std::chrono::nanoseconds(dvsync_->WaitTime()), [this] { return dvsync_->WaitCond(); });
416 } else {
417 if (!(hasVsync_.load() && isRs_)) {
418 con_.wait(locker);
419 }
420 hasVsync_.store(false);
421 }
422 if (pendingRNVInVsync_) {
423 return;
424 }
425 if (IsDVsyncOn()) {
426 std::pair<bool, int64_t> result = dvsync_->DoPreExecute(locker, con_);
427 if (result.first) {
428 event_.timestamp = result.second;
429 lastDVsyncTS_.store(result.second);
430 event_.vsyncCount++;
431 if (vsyncEnabled_ == false) {
432 ScopedBytrace func(name_ + "_EnableVsync");
433 EnableVSync();
434 }
435 }
436 }
437 #else
438 con_.wait(locker);
439 #endif
440 }
441
Now()442 int64_t Now()
443 {
444 const auto &now = std::chrono::steady_clock::now().time_since_epoch();
445 return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
446 }
447
WaitForVsyncOrTimeOut(std::unique_lock<std::mutex> & locker)448 void VSyncDistributor::WaitForVsyncOrTimeOut(std::unique_lock<std::mutex> &locker)
449 {
450 #if defined(RS_ENABLE_DVSYNC)
451 dvsync_->RNVNotify();
452 #endif
453 if (con_.wait_for(locker, std::chrono::milliseconds(SOFT_VSYNC_PERIOD)) ==
454 std::cv_status::timeout) {
455 event_.timestamp = Now();
456 event_.vsyncCount++;
457 }
458 }
459
ThreadMain()460 void VSyncDistributor::ThreadMain()
461 {
462 // set thread priorty
463 setpriority(PRIO_PROCESS, 0, THREAD_PRIORTY);
464 struct sched_param param = {0};
465 param.sched_priority = SCHED_PRIORITY;
466 sched_setscheduler(0, SCHED_FIFO, ¶m);
467
468 #ifdef COMPOSER_SCHED_ENABLE
469 std::string threadName = "VSync-" + name_;
470 SubScribeSystemAbility(threadName);
471 #endif
472
473 int64_t timestamp;
474 while (vsyncThreadRunning_ == true) {
475 std::vector<sptr<VSyncConnection>> conns;
476 {
477 bool waitForVSync = false;
478 std::unique_lock<std::mutex> locker(mutex_);
479 CollectConns(waitForVSync, timestamp, conns, true);
480 // no vsync signal
481 if (timestamp == 0) {
482 // there is some connections request next vsync, enable vsync if vsync disable and
483 // and start the software vsync with wait_for function
484 if (waitForVSync == true && vsyncEnabled_ == false) {
485 EnableVSync();
486 WaitForVsyncOrTimeOut(locker);
487 } else {
488 // just wait request or vsync signal
489 WaitForVsyncOrRequest(locker);
490 }
491 RS_TRACE_NAME_FMT("%s_continue: waitForVSync %d, vsyncEnabled %d, dvsyncOn %d",
492 name_.c_str(), waitForVSync, vsyncEnabled_, IsDVsyncOn());
493 if ((isRs_ && event_.timestamp == 0) || !IsDVsyncOn()) {
494 continue;
495 } else {
496 timestamp = event_.timestamp;
497 }
498 } else if ((timestamp > 0) && (waitForVSync == false) && (isRs_ || !IsDVsyncOn())) {
499 // if there is a vsync signal but no vaild connections, we should disable vsync
500 RS_TRACE_NAME_FMT("%s_DisableVSync, there is no valid connections", name_.c_str());
501 DisableVSync();
502 continue;
503 }
504 }
505 if (!PostVSyncEventPreProcess(timestamp, conns)) {
506 continue;
507 } else {
508 // IMPORTANT: ScopedDebugTrace here will cause frame loss.
509 RS_TRACE_NAME_FMT("%s_SendVsync", name_.c_str());
510 }
511 PostVSyncEvent(conns, timestamp, true);
512 }
513 }
514
CollectConns(bool & waitForVSync,int64_t & timestamp,std::vector<sptr<VSyncConnection>> & conns,bool isDvsyncThread)515 void VSyncDistributor::CollectConns(bool &waitForVSync, int64_t ×tamp,
516 std::vector<sptr<VSyncConnection>> &conns, bool isDvsyncThread)
517 {
518 if (isDvsyncThread) {
519 timestamp = event_.timestamp;
520 event_.timestamp = 0;
521 }
522 if (vsyncMode_ == VSYNC_MODE_LTPO) {
523 CollectConnectionsLTPO(waitForVSync, timestamp, conns, event_.vsyncPulseCount, isDvsyncThread);
524 } else {
525 CollectConnections(waitForVSync, timestamp, conns, event_.vsyncCount, isDvsyncThread);
526 }
527 }
528
PostVSyncEventPreProcess(int64_t & timestamp,std::vector<sptr<VSyncConnection>> & conns)529 bool VSyncDistributor::PostVSyncEventPreProcess(int64_t ×tamp, std::vector<sptr<VSyncConnection>> &conns)
530 {
531 #if defined(RS_ENABLE_DVSYNC)
532 bool waitForVSync = false;
533 // ensure the preexecution only gets ahead for at most one period(i.e., 3 buffer rotation)
534 if (IsDVsyncOn()) {
535 {
536 std::unique_lock<std::mutex> locker(mutex_);
537 dvsync_->MarkDistributorSleep(true);
538 dvsync_->RNVNotify();
539 dvsync_->DelayBeforePostEvent(event_.timestamp, locker);
540 dvsync_->MarkDistributorSleep(false);
541 CollectConns(waitForVSync, timestamp, conns, true);
542 hasVsync_.store(false);
543 }
544 // if getting switched into vsync mode after sleep
545 if (!IsDVsyncOn()) {
546 ScopedBytrace func("NoAccumulateInVsync");
547 lastDVsyncTS_.store(0); // ensure further OnVSyncEvent do not skip
548 for (auto conn : conns) {
549 RequestNextVSync(conn);
550 } // resend RNV for vsync
551 return false; // do not accumulate frame;
552 }
553 } else {
554 std::unique_lock<std::mutex> locker(mutex_);
555 hasVsync_.store(false);
556 }
557 {
558 std::unique_lock<std::mutex> locker(mutex_);
559 pendingRNVInVsync_ = false;
560 if (IsUiDvsyncOn()) {
561 event_.period = dvsync_->GetPeriod();
562 }
563 }
564 #endif
565 return true;
566 }
567
EnableVSync()568 void VSyncDistributor::EnableVSync()
569 {
570 if (controller_ != nullptr && vsyncEnabled_ == false) {
571 controller_->SetCallback(this);
572 controller_->SetEnable(true, vsyncEnabled_);
573 #if defined(RS_ENABLE_DVSYNC)
574 dvsync_->RecordEnableVsync();
575 #endif
576 }
577 }
578
DisableVSync()579 void VSyncDistributor::DisableVSync()
580 {
581 if (controller_ != nullptr && vsyncEnabled_ == true) {
582 controller_->SetEnable(false, vsyncEnabled_);
583 }
584 }
585
586 #if defined(RS_ENABLE_DVSYNC)
OnDVSyncTrigger(int64_t now,int64_t period,uint32_t refreshRate,VSyncMode vsyncMode)587 void VSyncDistributor::OnDVSyncTrigger(int64_t now, int64_t period, uint32_t refreshRate, VSyncMode vsyncMode)
588 {
589 std::unique_lock<std::mutex> locker(mutex_);
590 vsyncMode_ = vsyncMode;
591 dvsync_->RuntimeSwitch();
592 if (IsDVsyncOn()) {
593 RS_TRACE_NAME_FMT("VSyncD onVSyncEvent, now:%ld", now);
594 } else {
595 RS_TRACE_NAME_FMT("VSync onVSyncEvent, now:%ld", now);
596 }
597 event_.period = period;
598
599 dvsync_->RecordVSync(now, period, refreshRate);
600 dvsync_->NotifyPreexecuteWait();
601
602 SendConnectionsToVSyncWindow(now, period, refreshRate, vsyncMode, locker);
603 // when dvsync switch to vsync, skip all vsync events within one period from the pre-rendered timestamp
604 if (dvsync_->NeedSkipDVsyncPrerenderedFrame()) {
605 return;
606 }
607
608 // When vsync switches to dvsync, need to handle pending RNVs during vsync
609 if (!IsDVsyncOn() || pendingRNVInVsync_) {
610 event_.timestamp = now;
611 event_.vsyncCount++;
612 }
613
614 if (refreshRate > 0) {
615 event_.vsyncPulseCount += static_cast<int64_t>(VSYNC_MAX_REFRESHRATE / refreshRate);
616 generatorRefreshRate_ = refreshRate;
617 }
618
619 ChangeConnsRateLocked();
620 RS_TRACE_NAME_FMT("pendingRNVInVsync: %d DVSyncOn: %d isRS:%d", pendingRNVInVsync_, IsDVsyncOn(), isRs_);
621 if (dvsync_->WaitCond() || pendingRNVInVsync_) {
622 con_.notify_all();
623 } else {
624 CheckNeedDisableDvsync(now, period);
625 }
626 }
627 #endif
628
OnVSyncTrigger(int64_t now,int64_t period,uint32_t refreshRate,VSyncMode vsyncMode)629 void VSyncDistributor::OnVSyncTrigger(int64_t now, int64_t period, uint32_t refreshRate, VSyncMode vsyncMode)
630 {
631 std::vector<sptr<VSyncConnection>> conns;
632 uint32_t generatorRefreshRate;
633 int64_t vsyncCount;
634
635 {
636 bool waitForVSync = false;
637 std::lock_guard<std::mutex> locker(mutex_);
638 event_.vsyncCount++;
639 vsyncCount = event_.vsyncCount;
640 #if defined(RS_ENABLE_DVSYNC)
641 if (dvsync_->IsFeatureEnabled()) {
642 dvsync_->RecordVSync(now, period, refreshRate);
643 }
644 #endif
645 if (refreshRate > 0) {
646 event_.vsyncPulseCount += static_cast<int64_t>(VSYNC_MAX_REFRESHRATE / refreshRate);
647 generatorRefreshRate_ = refreshRate;
648 }
649 vsyncMode_ = vsyncMode;
650 ChangeConnsRateLocked();
651
652 if (vsyncMode_ == VSYNC_MODE_LTPO) {
653 CollectConnectionsLTPO(waitForVSync, now, conns, event_.vsyncPulseCount);
654 } else {
655 CollectConnections(waitForVSync, now, conns, event_.vsyncCount);
656 }
657 if (!waitForVSync) {
658 DisableVSync();
659 return;
660 }
661
662 countTraceValue_ = (countTraceValue_ + 1) % 2; // 2 : change num
663 CountTrace(HITRACE_TAG_GRAPHIC_AGP, "VSync-" + name_, countTraceValue_);
664
665 generatorRefreshRate = generatorRefreshRate_;
666 #if defined(RS_ENABLE_DVSYNC)
667 if (dvsync_->IsFeatureEnabled()) {
668 dvsync_->RecordPostEvent(conns, now);
669 }
670 #endif
671 }
672 OnVSyncTriggerPostEvent(now, generatorRefreshRate, conns, period, vsyncCount);
673 }
674
OnVSyncTriggerPostEvent(int64_t now,uint32_t generatorRefreshRate,std::vector<sptr<VSyncConnection>> & conns,int64_t period,int64_t vsyncCount)675 void VSyncDistributor::OnVSyncTriggerPostEvent(int64_t now, uint32_t generatorRefreshRate,
676 std::vector<sptr<VSyncConnection>>& conns, int64_t period, int64_t vsyncCount)
677 {
678 for (uint32_t i = 0; i < conns.size(); i++) {
679 int64_t actualPeriod = period;
680 if ((generatorRefreshRate > 0) && (conns[i]->refreshRate_ > 0) &&
681 (generatorRefreshRate % conns[i]->refreshRate_ == 0)) {
682 actualPeriod = period * static_cast<int64_t>(generatorRefreshRate / conns[i]->refreshRate_);
683 }
684 int32_t ret = conns[i]->PostEvent(now, actualPeriod, vsyncCount);
685 VLOGD("Distributor name:%{public}s, connection name:%{public}s, ret:%{public}d",
686 name_.c_str(), conns[i]->info_.name.c_str(), ret);
687 if (ret == 0 || ret == ERRNO_OTHER) {
688 RemoveConnection(conns[i]);
689 } else if (ret == ERRNO_EAGAIN) {
690 std::lock_guard<std::mutex> locker(mutex_);
691 // Trigger VSync Again for LTPO
692 conns[i]->triggerThisTime_ = true;
693 // Exclude SetVSyncRate for LTPS
694 if (conns[i]->rate_ < 0) {
695 conns[i]->rate_ = 0;
696 }
697 }
698 }
699 }
700
OnVSyncEvent(int64_t now,int64_t period,uint32_t refreshRate,VSyncMode vsyncMode)701 void VSyncDistributor::OnVSyncEvent(int64_t now, int64_t period, uint32_t refreshRate, VSyncMode vsyncMode)
702 {
703 #if defined(RS_ENABLE_DVSYNC)
704 bool needDVSyncTrigger = true;
705 if (dvsync_->IsFeatureEnabled()) {
706 std::unique_lock<std::mutex> locker(mutex_);
707 dvsync_->ChangeState(now);
708 needDVSyncTrigger = dvsync_->NeedDVSyncTrigger();
709 }
710 if (dvsync_->IsFeatureEnabled() && needDVSyncTrigger) {
711 OnDVSyncTrigger(now, period, refreshRate, vsyncMode);
712 } else
713 #endif
714 {
715 OnVSyncTrigger(now, period, refreshRate, vsyncMode);
716 }
717 }
718
719 #if defined(RS_ENABLE_DVSYNC)
SendConnectionsToVSyncWindow(int64_t now,int64_t period,uint32_t refreshRate,VSyncMode vsyncMode,std::unique_lock<std::mutex> & locker)720 void VSyncDistributor::SendConnectionsToVSyncWindow(int64_t now, int64_t period, uint32_t refreshRate,
721 VSyncMode vsyncMode, std::unique_lock<std::mutex> &locker)
722 {
723 std::vector<sptr<VSyncConnection>> conns;
724 bool waitForVSync = false;
725 if (isRs_ || GetUIDVsyncPid() == 0) {
726 return;
727 }
728 CollectConns(waitForVSync, now, conns, false);
729 locker.unlock();
730 PostVSyncEvent(conns, now, false);
731 locker.lock();
732 }
733
GetUIDVsyncPid()734 int32_t VSyncDistributor::GetUIDVsyncPid()
735 {
736 int32_t pid = 0;
737 if (!isRs_) {
738 pid = dvsync_->GetProxyPid();
739 }
740 return pid;
741 }
742 #endif
743
CheckNeedDisableDvsync(int64_t now,int64_t period)744 void VSyncDistributor::CheckNeedDisableDvsync(int64_t now, int64_t period)
745 {
746 #if defined(RS_ENABLE_DVSYNC)
747 if (!isRs_ && IsDVsyncOn()) {
748 return;
749 }
750 // When Dvsync on, if the RequestNextVsync is not invoked within three period and SetVSyncRate
751 // is not invoked either, execute DisableVSync.
752 for (uint32_t i = 0; i < connections_.size(); i++) {
753 if (connections_[i]->triggerThisTime_ || connections_[i]->rate_ >= 0) {
754 return;
755 }
756 }
757 if (now - dvsync_->GetLastRnvTS() > 3 * period) { // 3 period
758 ScopedBytrace func(name_ + "_DisableVsync");
759 DisableVSync();
760 }
761 #endif
762 }
763
764 /* std::pair<id, refresh rate> */
OnConnsRefreshRateChanged(const std::vector<std::pair<uint64_t,uint32_t>> & refreshRates)765 void VSyncDistributor::OnConnsRefreshRateChanged(const std::vector<std::pair<uint64_t, uint32_t>> &refreshRates)
766 {
767 std::lock_guard<std::mutex> locker(changingConnsRefreshRatesMtx_);
768 for (auto refreshRate : refreshRates) {
769 bool found = false;
770 for (auto it = changingConnsRefreshRates_.begin(); it != changingConnsRefreshRates_.end(); it++) {
771 if ((*it).first == refreshRate.first) { // first is linkerId
772 (*it).second = refreshRate.second; // second is refreshRate
773 found = true;
774 break;
775 }
776 }
777 if (!found) {
778 changingConnsRefreshRates_.push_back(refreshRate);
779 }
780 }
781 }
782
SubScribeSystemAbility(const std::string & threadName)783 void VSyncDistributor::SubScribeSystemAbility(const std::string& threadName)
784 {
785 VLOGI("%{public}s", __func__);
786 sptr<ISystemAbilityManager> systemAbilityManager =
787 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
788 if (!systemAbilityManager) {
789 VLOGE("%{public}s failed to get system ability manager client", __func__);
790 return;
791 }
792 std::string strUid = std::to_string(getuid());
793 std::string strPid = std::to_string(getpid());
794 std::string strTid = std::to_string(gettid());
795
796 saStatusChangeListener_ = new (std::nothrow)VSyncSystemAbilityListener(threadName, strUid, strPid, strTid);
797 int32_t ret = systemAbilityManager->SubscribeSystemAbility(RES_SCHED_SYS_ABILITY_ID, saStatusChangeListener_);
798 if (ret != ERR_OK) {
799 VLOGE("%{public}s subscribe system ability %{public}d failed.", __func__, RES_SCHED_SYS_ABILITY_ID);
800 saStatusChangeListener_ = nullptr;
801 }
802 }
803
CollectConnections(bool & waitForVSync,int64_t timestamp,std::vector<sptr<VSyncConnection>> & conns,int64_t vsyncCount,bool isDvsyncThread)804 void VSyncDistributor::CollectConnections(bool &waitForVSync, int64_t timestamp,
805 std::vector<sptr<VSyncConnection>> &conns, int64_t vsyncCount, bool isDvsyncThread)
806 {
807 #if defined(RS_ENABLE_DVSYNC)
808 auto uiDVsyncPid = GetUIDVsyncPid();
809 #endif
810 for (uint32_t i = 0; i < connections_.size(); i++) {
811 #if defined(RS_ENABLE_DVSYNC)
812 if (uiDVsyncPid != 0 && ((!isDvsyncThread && connections_[i]->proxyPid_ == uiDVsyncPid) ||
813 (isDvsyncThread && connections_[i]->proxyPid_ != uiDVsyncPid))) {
814 continue;
815 }
816 #endif
817 int32_t rate = connections_[i]->highPriorityState_ ? connections_[i]->highPriorityRate_ :
818 connections_[i]->rate_;
819
820 if (rate < 0) {
821 continue;
822 }
823
824 if (rate == 0) { // for RequestNextVSync
825 waitForVSync = true;
826 if (timestamp > 0) {
827 connections_[i]->rate_ = -1;
828 connections_[i]->triggerThisTime_ = false;
829 conns.push_back(connections_[i]);
830 }
831 continue;
832 }
833
834 RS_TRACE_NAME_FMT("CollectConnections name:%s, proxyPid:%d, highPriorityState_:%d, highPriorityRate_:%d"
835 ", rate_:%d, timestamp:%ld, vsyncCount:%ld", connections_[i]->info_.name_.c_str(),
836 connections_[i]->proxyPid_, connections_[i]->highPriorityState_,
837 connections_[i]->highPriorityRate_, connections_[i]->rate_, timestamp, vsyncCount);
838
839 if (connections_[i]->rate_ == 0) { // for SetHighPriorityVSyncRate with RequestNextVSync
840 waitForVSync = true;
841 if (timestamp > 0 && (vsyncCount % rate == 0)) {
842 connections_[i]->rate_ = -1;
843 connections_[i]->triggerThisTime_ = false;
844 conns.push_back(connections_[i]);
845 }
846 } else if (connections_[i]->rate_ > 0) { // for SetVSyncRate
847 waitForVSync = true;
848 if (timestamp > 0 && (vsyncCount % rate == 0)) {
849 conns.push_back(connections_[i]);
850 }
851 }
852 }
853 }
854
CollectConnectionsLTPO(bool & waitForVSync,int64_t timestamp,std::vector<sptr<VSyncConnection>> & conns,int64_t vsyncCount,bool isDvsyncThread)855 void VSyncDistributor::CollectConnectionsLTPO(bool &waitForVSync, int64_t timestamp,
856 std::vector<sptr<VSyncConnection>> &conns, int64_t vsyncCount, bool isDvsyncThread)
857 {
858 #if defined(RS_ENABLE_DVSYNC)
859 auto uiDVsyncPid = GetUIDVsyncPid();
860 #endif
861 for (uint32_t i = 0; i < connections_.size(); i++) {
862 #if defined(RS_ENABLE_DVSYNC)
863 if (uiDVsyncPid != 0 && ((!isDvsyncThread && connections_[i]->proxyPid_ == uiDVsyncPid) ||
864 (isDvsyncThread && connections_[i]->proxyPid_ != uiDVsyncPid))) {
865 continue;
866 }
867 #endif
868 SCOPED_DEBUG_TRACE_FMT("CollectConnectionsLTPO, i:%d, name:%s, rate:%d, vsyncPulseFreq:%u"
869 ", referencePulseCount:%ld, vsyncCount:%d", i, connections_[i]->info_.name_.c_str(), connections_[i]->rate_,
870 connections_[i]->vsyncPulseFreq_, connections_[i]->referencePulseCount_, vsyncCount);
871 if (!connections_[i]->triggerThisTime_ && connections_[i]->rate_ <= 0) {
872 continue;
873 }
874 waitForVSync = true;
875 if (timestamp <= 0) {
876 break;
877 }
878 int64_t vsyncPulseFreq = static_cast<int64_t>(connections_[i]->vsyncPulseFreq_);
879 if ((vsyncCount - connections_[i]->referencePulseCount_) % vsyncPulseFreq == 0) {
880 connections_[i]->triggerThisTime_ = false;
881 if (connections_[i]->rate_ == 0) {
882 connections_[i]->rate_ = -1;
883 }
884 conns.push_back(connections_[i]);
885 }
886 }
887 }
888
PostVSyncEvent(const std::vector<sptr<VSyncConnection>> & conns,int64_t timestamp,bool isDvsyncThread)889 void VSyncDistributor::PostVSyncEvent(const std::vector<sptr<VSyncConnection>> &conns,
890 int64_t timestamp, bool isDvsyncThread)
891 {
892 #if defined(RS_ENABLE_DVSYNC)
893 if (isDvsyncThread) {
894 std::unique_lock<std::mutex> locker(mutex_);
895 dvsync_->RecordPostEvent(conns, timestamp);
896 }
897 #endif
898 uint32_t generatorRefreshRate = 0;
899 int64_t eventPeriod = 0;
900 int64_t vsyncCount = 0;
901 {
902 std::unique_lock<std::mutex> locker(mutex_);
903 generatorRefreshRate = generatorRefreshRate_;
904 eventPeriod = event_.period;
905 vsyncCount = event_.vsyncCount;
906 }
907 for (uint32_t i = 0; i < conns.size(); i++) {
908 int64_t period = eventPeriod;
909 if ((generatorRefreshRate > 0) && (conns[i]->refreshRate_ > 0) &&
910 (generatorRefreshRate % conns[i]->refreshRate_ == 0)) {
911 period = eventPeriod * static_cast<int64_t>(generatorRefreshRate / conns[i]->refreshRate_);
912 }
913 int32_t ret = conns[i]->PostEvent(timestamp, period, vsyncCount);
914 VLOGD("Distributor name:%{public}s, connection name:%{public}s, ret:%{public}d",
915 name_.c_str(), conns[i]->info_.name_.c_str(), ret);
916 if (ret == 0 || ret == ERRNO_OTHER) {
917 RemoveConnection(conns[i]);
918 } else if (ret == ERRNO_EAGAIN) {
919 std::unique_lock<std::mutex> locker(mutex_);
920 // Trigger VSync Again for LTPO
921 conns[i]->triggerThisTime_ = true;
922 #if defined(RS_ENABLE_DVSYNC)
923 if (isDvsyncThread) {
924 hasVsync_.store(true);
925 }
926 #endif
927 // Exclude SetVSyncRate for LTPS
928 if (conns[i]->rate_ < 0) {
929 conns[i]->rate_ = 0;
930 }
931 }
932 }
933 }
934
RequestNextVSync(const sptr<VSyncConnection> & connection,const std::string & fromWhom,int64_t lastVSyncTS)935 VsyncError VSyncDistributor::RequestNextVSync(const sptr<VSyncConnection> &connection, const std::string &fromWhom,
936 int64_t lastVSyncTS)
937 {
938 if (connection == nullptr) {
939 VLOGE("connection is nullptr");
940 return VSYNC_ERROR_NULLPTR;
941 }
942
943 ScopedBytrace func(connection->info_.name_ + "_RequestNextVSync");
944 std::unique_lock<std::mutex> locker(mutex_);
945
946 #if defined(RS_ENABLE_DVSYNC)
947 if (IsDVsyncOn() && isRs_ && dvsync_->NeedDVSyncRNV()) {
948 dvsync_->RNVWait(locker);
949 }
950 #endif
951
952 auto it = find(connections_.begin(), connections_.end(), connection);
953 if (it == connections_.end()) {
954 VLOGE("connection is invalid arguments");
955 #if defined(RS_ENABLE_DVSYNC)
956 if (IsDVsyncOn()) {
957 dvsync_->RNVNotify();
958 }
959 #endif
960 return VSYNC_ERROR_INVALID_ARGUMENTS;
961 }
962 // record RNV and lastVSyncTS for D-VSYNC
963 #if defined(RS_ENABLE_DVSYNC)
964 dvsync_->RecordRNV(connection, fromWhom, lastVSyncTS);
965 if (!IsDVsyncOn()) {
966 pendingRNVInVsync_ = true;
967 }
968 #endif
969 if (connection->rate_ < 0) {
970 connection->rate_ = 0;
971 }
972 connection->triggerThisTime_ = true;
973 #if defined(RS_ENABLE_DVSYNC)
974 hasVsync_.store(true);
975 if (dvsync_->IsFeatureEnabled() && dvsync_->NeedDVSyncRNV()) {
976 con_.notify_all();
977 } else
978 #endif
979 {
980 EnableVSync();
981 }
982 VLOGD("conn name:%{public}s, rate:%{public}d", connection->info_.name_.c_str(), connection->rate_);
983 return VSYNC_ERROR_OK;
984 }
985
SetVSyncRate(int32_t rate,const sptr<VSyncConnection> & connection)986 VsyncError VSyncDistributor::SetVSyncRate(int32_t rate, const sptr<VSyncConnection>& connection)
987 {
988 if (rate < -1 || connection == nullptr) {
989 return VSYNC_ERROR_INVALID_ARGUMENTS;
990 }
991 std::lock_guard<std::mutex> locker(mutex_);
992 auto it = find(connections_.begin(), connections_.end(), connection);
993 if (it == connections_.end()) {
994 return VSYNC_ERROR_INVALID_ARGUMENTS;
995 }
996 if (connection->rate_ == rate) {
997 return VSYNC_ERROR_INVALID_ARGUMENTS;
998 }
999 connection->rate_ = rate;
1000 VLOGD("conn name:%{public}s", connection->info_.name_.c_str());
1001 #if defined(RS_ENABLE_DVSYNC)
1002 if (dvsync_->IsFeatureEnabled()) {
1003 con_.notify_all();
1004 } else
1005 #endif
1006 {
1007 EnableVSync();
1008 }
1009 return VSYNC_ERROR_OK;
1010 }
1011
SetHighPriorityVSyncRate(int32_t highPriorityRate,const sptr<VSyncConnection> & connection)1012 VsyncError VSyncDistributor::SetHighPriorityVSyncRate(int32_t highPriorityRate, const sptr<VSyncConnection>& connection)
1013 {
1014 if (highPriorityRate <= 0 || connection == nullptr) {
1015 return VSYNC_ERROR_INVALID_ARGUMENTS;
1016 }
1017
1018 std::lock_guard<std::mutex> locker(mutex_);
1019 auto it = find(connections_.begin(), connections_.end(), connection);
1020 if (it == connections_.end()) {
1021 return VSYNC_ERROR_INVALID_ARGUMENTS;
1022 }
1023 if (connection->highPriorityRate_ == highPriorityRate) {
1024 return VSYNC_ERROR_INVALID_ARGUMENTS;
1025 }
1026 connection->highPriorityRate_ = highPriorityRate;
1027 connection->highPriorityState_ = true;
1028 VLOGD("in, conn name:%{public}s, highPriorityRate:%{public}d", connection->info_.name_.c_str(),
1029 connection->highPriorityRate_);
1030 #if defined(RS_ENABLE_DVSYNC)
1031 if (dvsync_->IsFeatureEnabled()) {
1032 con_.notify_all();
1033 } else
1034 #endif
1035 {
1036 EnableVSync();
1037 }
1038 return VSYNC_ERROR_OK;
1039 }
1040
QosGetPidByName(const std::string & name,uint32_t & pid)1041 VsyncError VSyncDistributor::QosGetPidByName(const std::string& name, uint32_t& pid)
1042 {
1043 if (name.find("WM") == std::string::npos && name.find("ArkWebCore") == std::string::npos
1044 && name.find("NWeb") == std::string::npos) {
1045 return VSYNC_ERROR_INVALID_ARGUMENTS;
1046 }
1047 std::string::size_type pos = name.find("_");
1048 if (pos == std::string::npos) {
1049 return VSYNC_ERROR_INVALID_ARGUMENTS;
1050 }
1051 pid = (uint32_t)stoi(name.substr(pos + 1));
1052 return VSYNC_ERROR_OK;
1053 }
1054
SetQosVSyncRateByPid(uint32_t pid,int32_t rate,bool isSystemAnimateScene)1055 VsyncError VSyncDistributor::SetQosVSyncRateByPid(uint32_t pid, int32_t rate, bool isSystemAnimateScene)
1056 {
1057 // only set vsync rate by pid in SystemAnimateSecne
1058 if (!isSystemAnimateScene && rate != DEFAULT_VSYNC_RATE) {
1059 return VSYNC_ERROR_OK;
1060 }
1061 auto iter = connectionsMap_.find(pid);
1062 if (iter == connectionsMap_.end()) {
1063 VLOGD("%{public}s:%{public}d pid[%{public}u] can not found", __func__, __LINE__, pid);
1064 return VSYNC_ERROR_INVALID_ARGUMENTS;
1065 }
1066 bool isNeedNotify = false;
1067 for (auto connection : iter->second) {
1068 uint32_t tmpPid;
1069 if (QosGetPidByName(connection->info_.name_, tmpPid) != VSYNC_ERROR_OK || tmpPid != pid) {
1070 continue;
1071 }
1072 if (connection->highPriorityRate_ != rate) {
1073 connection->highPriorityRate_ = rate;
1074 connection->highPriorityState_ = true;
1075 VLOGD("in, conn name:%{public}s, highPriorityRate:%{public}d", connection->info_.name_.c_str(),
1076 connection->highPriorityRate_);
1077 isNeedNotify = true;
1078 }
1079 }
1080 if (isNeedNotify) {
1081 #if defined(RS_ENABLE_DVSYNC)
1082 if (dvsync_->IsFeatureEnabled()) {
1083 con_.notify_all();
1084 } else
1085 #endif
1086 {
1087 EnableVSync();
1088 }
1089 }
1090 return VSYNC_ERROR_OK;
1091 }
1092
ExtractPid(uint64_t id)1093 constexpr pid_t VSyncDistributor::ExtractPid(uint64_t id)
1094 {
1095 constexpr uint32_t bits = 32u;
1096 return static_cast<pid_t>(id >> bits);
1097 }
1098
SetQosVSyncRate(uint64_t windowNodeId,int32_t rate,bool isSystemAnimateScene)1099 VsyncError VSyncDistributor::SetQosVSyncRate(uint64_t windowNodeId, int32_t rate, bool isSystemAnimateScene)
1100 {
1101 std::lock_guard<std::mutex> locker(mutex_);
1102 VsyncError resCode = SetQosVSyncRateByPid(ExtractPid(windowNodeId), rate, isSystemAnimateScene);
1103 auto iter = connectionsMap_.find(windowNodeId);
1104 if (iter == connectionsMap_.end()) {
1105 return resCode;
1106 }
1107
1108 bool isNeedNotify = false;
1109 for (auto& connection : iter->second) {
1110 if (connection && connection->highPriorityRate_ != rate) {
1111 connection->highPriorityRate_ = rate;
1112 connection->highPriorityState_ = true;
1113 VLOGD("in, conn name:%{public}s, highPriorityRate:%{public}d", connection->info_.name_.c_str(),
1114 connection->highPriorityRate_);
1115 isNeedNotify = true;
1116 }
1117 }
1118 if (isNeedNotify) {
1119 #if defined(RS_ENABLE_DVSYNC)
1120 if (dvsync_->IsFeatureEnabled()) {
1121 con_.notify_all();
1122 } else
1123 #endif
1124 {
1125 EnableVSync();
1126 }
1127 }
1128 return VSYNC_ERROR_OK;
1129 }
1130
ChangeConnsRateLocked()1131 void VSyncDistributor::ChangeConnsRateLocked()
1132 {
1133 std::lock_guard<std::mutex> locker(changingConnsRefreshRatesMtx_);
1134 for (auto connRefreshRate : changingConnsRefreshRates_) {
1135 for (auto conn : connections_) {
1136 if (conn->id_ != connRefreshRate.first) {
1137 continue;
1138 }
1139 uint32_t refreshRate = connRefreshRate.second;
1140 if ((generatorRefreshRate_ == 0) || (refreshRate == 0) ||
1141 (VSYNC_MAX_REFRESHRATE % refreshRate != 0) || (generatorRefreshRate_ % refreshRate != 0)) {
1142 conn->refreshRate_ = 0;
1143 conn->vsyncPulseFreq_ = 1;
1144 continue;
1145 }
1146 conn->refreshRate_ = refreshRate;
1147 conn->vsyncPulseFreq_ = VSYNC_MAX_REFRESHRATE / refreshRate;
1148 conn->referencePulseCount_ = event_.vsyncPulseCount;
1149 }
1150 }
1151 changingConnsRefreshRates_.clear();
1152 }
1153
IsDVsyncOn()1154 bool VSyncDistributor::IsDVsyncOn()
1155 {
1156 #if defined(RS_ENABLE_DVSYNC)
1157 return dvsync_->IsEnabledAndOn();
1158 #else
1159 return false;
1160 #endif
1161 }
1162
SetFrameIsRender(bool isRender)1163 void VSyncDistributor::SetFrameIsRender(bool isRender)
1164 {
1165 #if defined(RS_ENABLE_DVSYNC)
1166 std::unique_lock<std::mutex> locker(mutex_);
1167 ScopedBytrace trace("SetFrameIsRender:" + std::to_string(isRender));
1168 if (isRender) {
1169 dvsync_->UnMarkRSNotRendering();
1170 } else {
1171 dvsync_->MarkRSNotRendering();
1172 }
1173 #endif
1174 }
1175
MarkRSAnimate()1176 void VSyncDistributor::MarkRSAnimate()
1177 {
1178 #if defined(RS_ENABLE_DVSYNC)
1179 dvsync_->MarkRSAnimate();
1180 #endif
1181 }
1182
UnmarkRSAnimate()1183 void VSyncDistributor::UnmarkRSAnimate()
1184 {
1185 #if defined(RS_ENABLE_DVSYNC)
1186 dvsync_->UnmarkRSAnimate();
1187 #endif
1188 }
1189
HasPendingUIRNV()1190 bool VSyncDistributor::HasPendingUIRNV()
1191 {
1192 #if defined(RS_ENABLE_DVSYNC)
1193 return dvsync_->HasPendingUIRNV();
1194 #else
1195 return false;
1196 #endif
1197 }
1198
SetUiDvsyncSwitch(bool dvsyncSwitch,const sptr<VSyncConnection> & connection)1199 VsyncError VSyncDistributor::SetUiDvsyncSwitch(bool dvsyncSwitch, const sptr<VSyncConnection> &connection)
1200 {
1201 #if defined(RS_ENABLE_DVSYNC)
1202 std::lock_guard<std::mutex> locker(mutex_);
1203 dvsync_->RuntimeMark(connection, dvsyncSwitch);
1204 #endif
1205 return VSYNC_ERROR_OK;
1206 }
1207
SetUiDvsyncConfig(int32_t bufferCount)1208 VsyncError VSyncDistributor::SetUiDvsyncConfig(int32_t bufferCount)
1209 {
1210 #if defined(RS_ENABLE_DVSYNC)
1211 std::lock_guard<std::mutex> locker(mutex_);
1212 dvsync_->SetUiDvsyncConfig(bufferCount);
1213 #endif
1214 return VSYNC_ERROR_OK;
1215 }
1216
SetNativeDVSyncSwitch(bool dvsyncSwitch,const sptr<VSyncConnection> & connection)1217 VsyncError VSyncDistributor::SetNativeDVSyncSwitch(bool dvsyncSwitch, const sptr<VSyncConnection> &connection)
1218 {
1219 #if defined(RS_ENABLE_DVSYNC)
1220 std::lock_guard<std::mutex> locker(mutex_);
1221 dvsync_->RuntimeMark(connection, dvsyncSwitch, true);
1222 #endif
1223 return VSYNC_ERROR_OK;
1224 }
1225
GetRefreshRate()1226 uint32_t VSyncDistributor::GetRefreshRate()
1227 {
1228 #if defined(RS_ENABLE_DVSYNC)
1229 std::lock_guard<std::mutex> locker(mutex_);
1230 return dvsync_->GetRefreshRate();
1231 #else
1232 return generatorRefreshRate_;
1233 #endif
1234 }
1235
RecordVsyncModeChange(uint32_t refreshRate,int64_t period)1236 void VSyncDistributor::RecordVsyncModeChange(uint32_t refreshRate, int64_t period)
1237 {
1238 #if defined(RS_ENABLE_DVSYNC)
1239 std::lock_guard<std::mutex> locker(mutex_);
1240 dvsync_->RecordVsyncModeChange(refreshRate, period);
1241 #endif
1242 }
1243
IsUiDvsyncOn()1244 bool VSyncDistributor::IsUiDvsyncOn()
1245 {
1246 #if defined(RS_ENABLE_DVSYNC)
1247 return dvsync_->IsUiDvsyncOn();
1248 #else
1249 return false;
1250 #endif
1251 }
GetUiCommandDelayTime()1252 int64_t VSyncDistributor::GetUiCommandDelayTime()
1253 {
1254 #if defined(RS_ENABLE_DVSYNC)
1255 return dvsync_->GetUiCommandDelayTime();
1256 #else
1257 return 0;
1258 #endif
1259 }
1260
UpdatePendingReferenceTime(int64_t & timeStamp)1261 void VSyncDistributor::UpdatePendingReferenceTime(int64_t &timeStamp)
1262 {
1263 #if defined(RS_ENABLE_DVSYNC)
1264 if (IsDVsyncOn()) {
1265 dvsync_->UpdatePendingReferenceTime(timeStamp);
1266 }
1267 #endif
1268 }
1269
GetRealTimeOffsetOfDvsync(int64_t time)1270 uint64_t VSyncDistributor::GetRealTimeOffsetOfDvsync(int64_t time)
1271 {
1272 #if defined(RS_ENABLE_DVSYNC)
1273 if (IsDVsyncOn()) {
1274 return dvsync_->GetRealTimeOffsetOfDvsync(time);
1275 }
1276 #endif
1277 return 0;
1278 }
1279
SetHardwareTaskNum(uint32_t num)1280 void VSyncDistributor::SetHardwareTaskNum(uint32_t num)
1281 {
1282 #if defined(RS_ENABLE_DVSYNC)
1283 if (IsDVsyncOn()) {
1284 dvsync_->SetHardwareTaskNum(num);
1285 }
1286 #endif
1287 }
1288
SetHasNativeBuffer()1289 void VSyncDistributor::SetHasNativeBuffer()
1290 {
1291 #if defined(RS_ENABLE_DVSYNC)
1292 std::unique_lock<std::mutex> locker(mutex_);
1293 dvsync_->SetHasNativeBuffer();
1294 #endif
1295 }
1296 }
1297 }
1298