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