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