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