• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "vsync_distributor.h"
17 #include <chrono>
18 #include <condition_variable>
19 #include <algorithm>
20 #include <cstdint>
21 #include <mutex>
22 #include <sched.h>
23 #include <sys/resource.h>
24 #include <scoped_bytrace.h>
25 #include "vsync_log.h"
26 #include "vsync_type.h"
27 #include "vsync_generator.h"
28 
29 namespace OHOS {
30 namespace Rosen {
31 namespace {
32 constexpr int32_t SOFT_VSYNC_PERIOD = 16;
33 constexpr int32_t ERRNO_EAGAIN = -1;
34 constexpr int32_t ERRNO_OTHER = -2;
35 constexpr int32_t THREAD_PRIORTY = -6;
36 constexpr int32_t SCHED_PRIORITY = 2;
37 constexpr uint32_t SOCKET_CHANNEL_SIZE = 1024;
38 constexpr int32_t VSYNC_CONNECTION_MAX_SIZE = 128;
39 }
40 
VSyncConnectionDeathRecipient(wptr<VSyncConnection> conn)41 VSyncConnection::VSyncConnectionDeathRecipient::VSyncConnectionDeathRecipient(
42     wptr<VSyncConnection> conn) : conn_(conn)
43 {
44 }
45 
OnRemoteDied(const wptr<IRemoteObject> & token)46 void VSyncConnection::VSyncConnectionDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& token)
47 {
48     auto tokenSptr = token.promote();
49     if (tokenSptr == nullptr) {
50         VLOGW("%{public}s: can't promote remote object.", __func__);
51         return;
52     }
53     auto vsyncConn = conn_.promote();
54     if (vsyncConn == nullptr) {
55         VLOGW("%{public}s: VSyncConnection was dead, do nothing.", __func__);
56         return;
57     }
58     if (vsyncConn->token_ != tokenSptr) {
59         VLOGI("%{public}s: token doesn't match, ignore it.", __func__);
60         return;
61     }
62     VLOGD("%{public}s: clear socketPair, conn name:%{public}s.", __func__, vsyncConn->info_.name_.c_str());
63     VsyncError ret = vsyncConn->Destroy();
64     if (ret != VSYNC_ERROR_OK) {
65         VLOGE("vsync connection clearAll failed!");
66     }
67 }
68 
VSyncConnection(const sptr<VSyncDistributor> & distributor,std::string name,const sptr<IRemoteObject> & token,uint64_t id)69 VSyncConnection::VSyncConnection(
70     const sptr<VSyncDistributor>& distributor,
71     std::string name,
72     const sptr<IRemoteObject>& token,
73     uint64_t id)
74     : rate_(-1),
75       info_(name),
76       id_(id),
77       vsyncConnDeathRecipient_(new VSyncConnectionDeathRecipient(this)),
78       token_(token),
79       distributor_(distributor)
80 {
81     socketPair_ = new LocalSocketPair();
82     int32_t err = socketPair_->CreateChannel(SOCKET_CHANNEL_SIZE, SOCKET_CHANNEL_SIZE);
83     if (err != 0) {
84         ScopedBytrace func("Create socket channel failed, errno = " + std::to_string(errno));
85     }
86     if (token_ != nullptr) {
87         token_->AddDeathRecipient(vsyncConnDeathRecipient_);
88     }
89     proxyPid_ = GetCallingPid();
90     isDead_ = false;
91 }
92 
~VSyncConnection()93 VSyncConnection::~VSyncConnection()
94 {
95     if ((token_ != nullptr) && (vsyncConnDeathRecipient_ != nullptr)) {
96         token_->RemoveDeathRecipient(vsyncConnDeathRecipient_);
97     }
98 }
99 
RequestNextVSync()100 VsyncError VSyncConnection::RequestNextVSync()
101 {
102     std::unique_lock<std::mutex> locker(mutex_);
103     if (isDead_) {
104         VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
105         return VSYNC_ERROR_API_FAILED;
106     }
107     if (distributor_ == nullptr) {
108         return VSYNC_ERROR_NULLPTR;
109     }
110     const sptr<VSyncDistributor> distributor = distributor_.promote();
111     if (distributor == nullptr) {
112         return VSYNC_ERROR_NULLPTR;
113     }
114     return distributor->RequestNextVSync(this);
115 }
116 
GetReceiveFd(int32_t & fd)117 VsyncError VSyncConnection::GetReceiveFd(int32_t &fd)
118 {
119     std::unique_lock<std::mutex> locker(mutex_);
120     if (isDead_) {
121         VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
122         return VSYNC_ERROR_API_FAILED;
123     }
124     fd = socketPair_->GetReceiveDataFd();
125     return VSYNC_ERROR_OK;
126 }
127 
PostEvent(int64_t now,int64_t period,int64_t vsyncCount)128 int32_t VSyncConnection::PostEvent(int64_t now, int64_t period, int64_t vsyncCount)
129 {
130     sptr<LocalSocketPair> socketPair;
131     {
132         std::unique_lock<std::mutex> locker(mutex_);
133         if (isDead_) {
134             ScopedBytrace func("Vsync Client Connection is dead, conn: " + info_.name_);
135             VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
136             return ERRNO_OTHER;
137         }
138         socketPair = socketPair_;
139     }
140     if (socketPair == nullptr) {
141         ScopedBytrace func("socketPair is null, conn: " + info_.name_);
142         return ERRNO_OTHER;
143     }
144     ScopedBytrace func("SendVsyncTo conn: " + info_.name_ + ", now:" + std::to_string(now));
145     // 3 is array size.
146     int64_t data[3];
147     data[0] = now;
148     // 1, 2: index of array data.
149     data[1] = now + period;
150     data[2] = vsyncCount;
151     if ((CreateVSyncGenerator()->GetVSyncMode() == VSYNC_MODE_LTPS) && info_.name_ == "rs") {
152         // 5000000 is the vsync offset.
153         data[1] += period - 5000000;
154     }
155     int32_t ret = socketPair->SendData(data, sizeof(data));
156     if (ret > -1) {
157         ScopedDebugTrace successful("successful");
158         info_.postVSyncCount_++;
159     } else {
160         ScopedBytrace failed("failed");
161     }
162     return ret;
163 }
164 
SetVSyncRate(int32_t rate)165 VsyncError VSyncConnection::SetVSyncRate(int32_t rate)
166 {
167     std::unique_lock<std::mutex> locker(mutex_);
168     if (isDead_) {
169         VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
170         return VSYNC_ERROR_API_FAILED;
171     }
172     if (distributor_ == nullptr) {
173         return VSYNC_ERROR_NULLPTR;
174     }
175     const sptr<VSyncDistributor> distributor = distributor_.promote();
176     if (distributor == nullptr) {
177         return VSYNC_ERROR_NULLPTR;
178     }
179     return distributor->SetVSyncRate(rate, this);
180 }
181 
CleanAllLocked()182 VsyncError VSyncConnection::CleanAllLocked()
183 {
184     socketPair_ = nullptr;
185     const sptr<VSyncDistributor> distributor = distributor_.promote();
186     if (distributor == nullptr) {
187         return VSYNC_ERROR_OK;
188     }
189     VsyncError ret = distributor->RemoveConnection(this);
190     isDead_ = true;
191     return ret;
192 }
193 
Destroy()194 VsyncError VSyncConnection::Destroy()
195 {
196     std::unique_lock<std::mutex> locker(mutex_);
197     return CleanAllLocked();
198 }
199 
VSyncDistributor(sptr<VSyncController> controller,std::string name)200 VSyncDistributor::VSyncDistributor(sptr<VSyncController> controller, std::string name)
201     : controller_(controller), mutex_(), con_(), connections_(),
202     event_(), vsyncEnabled_(false), name_(name)
203 {
204     vsyncThreadRunning_ = true;
205     threadLoop_ = std::thread(std::bind(&VSyncDistributor::ThreadMain, this));
206     std::string threadName = "VSync-" + name;
207     pthread_setname_np(threadLoop_.native_handle(), threadName.c_str());
208 }
209 
~VSyncDistributor()210 VSyncDistributor::~VSyncDistributor()
211 {
212     {
213         std::unique_lock<std::mutex> locker(mutex_);
214         vsyncThreadRunning_ = false;
215     }
216     if (threadLoop_.joinable()) {
217         con_.notify_all();
218         threadLoop_.join();
219     }
220 }
221 
AddConnection(const sptr<VSyncConnection> & connection)222 VsyncError VSyncDistributor::AddConnection(const sptr<VSyncConnection>& connection)
223 {
224     if (connection == nullptr) {
225         return VSYNC_ERROR_NULLPTR;
226     }
227 
228     int32_t proxyPid = connection->proxyPid_;
229     std::lock_guard<std::mutex> locker(mutex_);
230     if (connectionCounter_[proxyPid] > VSYNC_CONNECTION_MAX_SIZE) {
231         VLOGE("You [%{public}d] have created too many vsync connection, please check!!!", proxyPid);
232         return VSYNC_ERROR_API_FAILED;
233     }
234 
235     auto it = std::find(connections_.begin(), connections_.end(), connection);
236     if (it != connections_.end()) {
237         return VSYNC_ERROR_INVALID_ARGUMENTS;
238     }
239     ScopedBytrace func("Add VSyncConnection: " + connection->info_.name_);
240     connections_.push_back(connection);
241     connectionCounter_[proxyPid]++;
242     uint32_t tmpPid;
243     if (QosGetPidByName(connection->info_.name_, tmpPid) == VSYNC_ERROR_OK) {
244         connectionsMap_[tmpPid].push_back(connection);
245     }
246     return VSYNC_ERROR_OK;
247 }
248 
RemoveConnection(const sptr<VSyncConnection> & connection)249 VsyncError VSyncDistributor::RemoveConnection(const sptr<VSyncConnection>& connection)
250 {
251     if (connection == nullptr) {
252         return VSYNC_ERROR_NULLPTR;
253     }
254     int32_t proxyPid = connection->proxyPid_;
255     std::lock_guard<std::mutex> locker(mutex_);
256     auto it = std::find(connections_.begin(), connections_.end(), connection);
257     if (it == connections_.end()) {
258         return VSYNC_ERROR_INVALID_ARGUMENTS;
259     }
260     ScopedBytrace func("Remove VSyncConnection: " + connection->info_.name_);
261     connections_.erase(it);
262     connectionCounter_[proxyPid]--;
263     if (connectionCounter_[proxyPid] == 0) {
264         connectionCounter_.erase(proxyPid);
265     }
266     uint32_t tmpPid;
267     if (QosGetPidByName(connection->info_.name_, tmpPid) == VSYNC_ERROR_OK) {
268         auto iter = connectionsMap_.find(tmpPid);
269         if (iter == connectionsMap_.end()) {
270             return VSYNC_ERROR_OK;
271         }
272         auto connIter = find(iter->second.begin(), iter->second.end(), connection);
273         iter->second.erase(connIter);
274         if (iter->second.empty()) {
275             connectionsMap_.erase(iter);
276         }
277     }
278     return VSYNC_ERROR_OK;
279 }
280 
ThreadMain()281 void VSyncDistributor::ThreadMain()
282 {
283     // set thread priorty
284     setpriority(PRIO_PROCESS, 0, THREAD_PRIORTY);
285     struct sched_param param = {0};
286     param.sched_priority = SCHED_PRIORITY;
287     sched_setscheduler(0, SCHED_FIFO, &param);
288 
289     int64_t timestamp;
290     int64_t vsyncCount;
291     while (vsyncThreadRunning_ == true) {
292         std::vector<sptr<VSyncConnection>> conns;
293         {
294             bool waitForVSync = false;
295             std::unique_lock<std::mutex> locker(mutex_);
296             timestamp = event_.timestamp;
297             event_.timestamp = 0;
298             vsyncCount = event_.vsyncCount;
299             if (vsyncMode_ == VSYNC_MODE_LTPO) {
300                 CollectConnectionsLTPO(waitForVSync, timestamp, conns, event_.vsyncPulseCount);
301             } else {
302                 CollectConnections(waitForVSync, timestamp, conns, vsyncCount);
303             }
304             // no vsync signal
305             if (timestamp == 0) {
306                 // there is some connections request next vsync, enable vsync if vsync disable and
307                 // and start the software vsync with wait_for function
308                 if (waitForVSync == true && vsyncEnabled_ == false) {
309                     EnableVSync();
310                     if (con_.wait_for(locker, std::chrono::milliseconds(SOFT_VSYNC_PERIOD)) ==
311                         std::cv_status::timeout) {
312                         const auto &now = std::chrono::steady_clock::now().time_since_epoch();
313                         timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
314                         event_.timestamp = timestamp;
315                         event_.vsyncCount++;
316                     }
317                 } else {
318                     // just wait request or vsync signal
319                     if (vsyncThreadRunning_ == true) {
320                         con_.wait(locker);
321                     }
322                 }
323                 ScopedBytrace func(name_ + "_continue: waitForVSync " + std::to_string(waitForVSync) +
324                     ", vsyncEnabled " + std::to_string(vsyncEnabled_));
325                 continue;
326             } else if ((timestamp > 0) && (waitForVSync == false)) {
327                 // if there is a vsync signal but no vaild connections, we should disable vsync
328                 ScopedBytrace func(name_ + "_DisableVSync, there is no valid connections");
329                 DisableVSync();
330                 continue;
331             }
332         }
333         {
334             // IMPORTANT: ScopedDebugTrace here will cause frame loss.
335             ScopedBytrace func(name_ + "_SendVsync");
336         }
337         PostVSyncEvent(conns, timestamp);
338     }
339 }
340 
EnableVSync()341 void VSyncDistributor::EnableVSync()
342 {
343     if (controller_ != nullptr && vsyncEnabled_ == false) {
344         controller_->SetCallback(this);
345         controller_->SetEnable(true, vsyncEnabled_);
346     }
347 }
348 
DisableVSync()349 void VSyncDistributor::DisableVSync()
350 {
351     if (controller_ != nullptr && vsyncEnabled_ == true) {
352         controller_->SetEnable(false, vsyncEnabled_);
353     }
354 }
355 
OnVSyncEvent(int64_t now,int64_t period,uint32_t refreshRate,VSyncMode vsyncMode)356 void VSyncDistributor::OnVSyncEvent(int64_t now, int64_t period, uint32_t refreshRate, VSyncMode vsyncMode)
357 {
358     std::lock_guard<std::mutex> locker(mutex_);
359     event_.timestamp = now;
360     event_.vsyncCount++;
361     event_.period = period;
362     if (refreshRate > 0) {
363         event_.vsyncPulseCount += static_cast<int64_t>(VSYNC_MAX_REFRESHRATE / refreshRate);
364         generatorRefreshRate_ = refreshRate;
365     }
366     vsyncMode_ = vsyncMode;
367     ChangeConnsRateLocked();
368     con_.notify_all();
369 }
370 
371 /* std::pair<id, refresh rate> */
OnConnsRefreshRateChanged(const std::vector<std::pair<uint64_t,uint32_t>> & refreshRates)372 void VSyncDistributor::OnConnsRefreshRateChanged(const std::vector<std::pair<uint64_t, uint32_t>> &refreshRates)
373 {
374     std::lock_guard<std::mutex> locker(changingConnsRefreshRatesMtx_);
375     changingConnsRefreshRates_ = refreshRates;
376 }
377 
CollectConnections(bool & waitForVSync,int64_t timestamp,std::vector<sptr<VSyncConnection>> & conns,int64_t vsyncCount)378 void VSyncDistributor::CollectConnections(bool &waitForVSync, int64_t timestamp,
379                                           std::vector<sptr<VSyncConnection>> &conns, int64_t vsyncCount)
380 {
381     for (uint32_t i = 0; i < connections_.size(); i++) {
382         int32_t rate = connections_[i]->highPriorityState_ ? connections_[i]->highPriorityRate_ :
383                                                              connections_[i]->rate_;
384         if (rate == 0) {  // for RequestNextVSync
385             waitForVSync = true;
386             if (timestamp > 0) {
387                 connections_[i]->rate_ = -1;
388                 conns.push_back(connections_[i]);
389                 connections_[i]->triggerThisTime_ = false;
390             }
391         } else if (rate > 0) {
392             ScopedBytrace trace("CollectConnections name:" + connections_[i]->info_.name_ +
393                                 ", proxyPid:" + std::to_string(connections_[i]->proxyPid_) +
394                                 ", highPriorityState_:" + std::to_string(connections_[i]->highPriorityState_) +
395                                 ", highPriorityRate_:" + std::to_string(connections_[i]->highPriorityRate_) +
396                                 ", rate_:" + std::to_string(connections_[i]->rate_) +
397                                 ", timestamp:" + std::to_string(timestamp) +
398                                 ", vsyncCount:" + std::to_string(vsyncCount));
399             if (connections_[i]->rate_ == 0) {  // for SetHighPriorityVSyncRate with RequestNextVSync
400                 waitForVSync = true;
401                 if (timestamp > 0 && (vsyncCount % rate == 0)) {
402                     connections_[i]->rate_ = -1;
403                     conns.push_back(connections_[i]);
404                     connections_[i]->triggerThisTime_ = false;
405                 }
406             } else if (connections_[i]->rate_ > 0) {  // for SetVSyncRate
407                 waitForVSync = true;
408                 if (timestamp > 0 && (vsyncCount % rate == 0)) {
409                     conns.push_back(connections_[i]);
410                 }
411             }
412         }
413     }
414 }
415 
CollectConnectionsLTPO(bool & waitForVSync,int64_t timestamp,std::vector<sptr<VSyncConnection>> & conns,int64_t vsyncCount)416 void VSyncDistributor::CollectConnectionsLTPO(bool &waitForVSync, int64_t timestamp,
417                                               std::vector<sptr<VSyncConnection>> &conns, int64_t vsyncCount)
418 {
419     for (uint32_t i = 0; i < connections_.size(); i++) {
420         if (!connections_[i]->triggerThisTime_ && connections_[i]->rate_ <= 0) {
421             continue;
422         }
423         waitForVSync = true;
424         int64_t vsyncPulseFreq = static_cast<int64_t>(connections_[i]->vsyncPulseFreq_);
425         if (timestamp > 0 &&
426             (vsyncCount - connections_[i]->referencePulseCount_) % vsyncPulseFreq == 0) {
427             conns.push_back(connections_[i]);
428             connections_[i]->triggerThisTime_ = false;
429             if (connections_[i]->rate_ == 0) {
430                 connections_[i]->rate_ = -1;
431             }
432         }
433     }
434 }
435 
PostVSyncEvent(const std::vector<sptr<VSyncConnection>> & conns,int64_t timestamp)436 void VSyncDistributor::PostVSyncEvent(const std::vector<sptr<VSyncConnection>> &conns, int64_t timestamp)
437 {
438     for (uint32_t i = 0; i < conns.size(); i++) {
439         int64_t period = event_.period;
440         if ((generatorRefreshRate_ > 0) && (conns[i]->refreshRate_ > 0) &&
441             (generatorRefreshRate_ % conns[i]->refreshRate_ == 0)) {
442             period = event_.period * static_cast<int64_t>(generatorRefreshRate_ / conns[i]->refreshRate_);
443         }
444         int32_t ret = conns[i]->PostEvent(timestamp, period, event_.vsyncCount);
445         VLOGD("Distributor name:%{public}s, connection name:%{public}s, ret:%{public}d",
446             name_.c_str(), conns[i]->info_.name_.c_str(), ret);
447         if (ret == 0 || ret == ERRNO_OTHER) {
448             RemoveConnection(conns[i]);
449         } else if (ret == ERRNO_EAGAIN) {
450             std::unique_lock<std::mutex> locker(mutex_);
451             // Trigger VSync Again for LTPO
452             conns[i]->triggerThisTime_ = true;
453             // Exclude SetVSyncRate for LTPS
454             if (conns[i]->rate_ < 0) {
455                 conns[i]->rate_ = 0;
456             }
457         }
458     }
459 }
460 
RequestNextVSync(const sptr<VSyncConnection> & connection)461 VsyncError VSyncDistributor::RequestNextVSync(const sptr<VSyncConnection>& connection)
462 {
463     if (connection == nullptr) {
464         VLOGE("connection is nullptr");
465         return VSYNC_ERROR_NULLPTR;
466     }
467     ScopedBytrace func(connection->info_.name_ + "_RequestNextVSync");
468     std::lock_guard<std::mutex> locker(mutex_);
469     auto it = find(connections_.begin(), connections_.end(), connection);
470     if (it == connections_.end()) {
471         VLOGE("connection is invalid arguments");
472         return VSYNC_ERROR_INVALID_ARGUMENTS;
473     }
474     if (connection->rate_ < 0) {
475         connection->rate_ = 0;
476     }
477     connection->triggerThisTime_ = true;
478     con_.notify_all();
479     VLOGD("conn name:%{public}s, rate:%{public}d", connection->info_.name_.c_str(), connection->rate_);
480     return VSYNC_ERROR_OK;
481 }
482 
SetVSyncRate(int32_t rate,const sptr<VSyncConnection> & connection)483 VsyncError VSyncDistributor::SetVSyncRate(int32_t rate, const sptr<VSyncConnection>& connection)
484 {
485     if (rate < -1 || connection == nullptr) {
486         return VSYNC_ERROR_INVALID_ARGUMENTS;
487     }
488     std::lock_guard<std::mutex> locker(mutex_);
489     auto it = find(connections_.begin(), connections_.end(), connection);
490     if (it == connections_.end()) {
491         return VSYNC_ERROR_INVALID_ARGUMENTS;
492     }
493     if (connection->rate_ == rate) {
494         return VSYNC_ERROR_INVALID_ARGUMENTS;
495     }
496     connection->rate_ = rate;
497     VLOGD("conn name:%{public}s", connection->info_.name_.c_str());
498     con_.notify_all();
499     return VSYNC_ERROR_OK;
500 }
501 
SetHighPriorityVSyncRate(int32_t highPriorityRate,const sptr<VSyncConnection> & connection)502 VsyncError VSyncDistributor::SetHighPriorityVSyncRate(int32_t highPriorityRate, const sptr<VSyncConnection>& connection)
503 {
504     if (highPriorityRate <= 0 || connection == nullptr) {
505         return VSYNC_ERROR_INVALID_ARGUMENTS;
506     }
507 
508     std::lock_guard<std::mutex> locker(mutex_);
509     auto it = find(connections_.begin(), connections_.end(), connection);
510     if (it == connections_.end()) {
511         return VSYNC_ERROR_INVALID_ARGUMENTS;
512     }
513     if (connection->highPriorityRate_ == highPriorityRate) {
514         return VSYNC_ERROR_INVALID_ARGUMENTS;
515     }
516     connection->highPriorityRate_ = highPriorityRate;
517     connection->highPriorityState_ = true;
518     VLOGD("in, conn name:%{public}s, highPriorityRate:%{public}d", connection->info_.name_.c_str(),
519           connection->highPriorityRate_);
520     con_.notify_all();
521     return VSYNC_ERROR_OK;
522 }
523 
GetVSyncConnectionInfos(std::vector<ConnectionInfo> & infos)524 VsyncError VSyncDistributor::GetVSyncConnectionInfos(std::vector<ConnectionInfo>& infos)
525 {
526     infos.clear();
527     for (auto &connection : connections_) {
528         infos.push_back(connection->info_);
529     }
530     return VSYNC_ERROR_OK;
531 }
532 
QosGetPidByName(const std::string & name,uint32_t & pid)533 VsyncError VSyncDistributor::QosGetPidByName(const std::string& name, uint32_t& pid)
534 {
535     if (name.find("WM") == std::string::npos && name.find("NWeb") == std::string::npos) {
536         return VSYNC_ERROR_INVALID_ARGUMENTS;
537     }
538     std::string::size_type pos = name.find("_");
539     if (pos == std::string::npos) {
540         return VSYNC_ERROR_INVALID_ARGUMENTS;
541     }
542     pid = (uint32_t)stoi(name.substr(pos + 1));
543     return VSYNC_ERROR_OK;
544 }
545 
SetQosVSyncRate(uint32_t pid,int32_t rate)546 VsyncError VSyncDistributor::SetQosVSyncRate(uint32_t pid, int32_t rate)
547 {
548     std::lock_guard<std::mutex> locker(mutex_);
549     auto iter = connectionsMap_.find(pid);
550     if (iter == connectionsMap_.end()) {
551         VLOGD("%{public}s:%{public}d pid[%{public}u] can not found", __func__, __LINE__, pid);
552         return VSYNC_ERROR_INVALID_ARGUMENTS;
553     }
554     bool isNeedNotify = false;
555     for (auto connection : iter->second) {
556         uint32_t tmpPid;
557         if (QosGetPidByName(connection->info_.name_, tmpPid) != VSYNC_ERROR_OK || tmpPid != pid) {
558             continue;
559         }
560         if (connection->highPriorityRate_ != rate) {
561             connection->highPriorityRate_ = rate;
562             connection->highPriorityState_ = true;
563             VLOGD("in, conn name:%{public}s, highPriorityRate:%{public}d", connection->info_.name_.c_str(),
564                 connection->highPriorityRate_);
565             isNeedNotify = true;
566         }
567     }
568     if (isNeedNotify) {
569         con_.notify_all();
570     }
571     return VSYNC_ERROR_OK;
572 }
573 
GetQosVSyncRateInfos(std::vector<std::pair<uint32_t,int32_t>> & vsyncRateInfos)574 VsyncError VSyncDistributor::GetQosVSyncRateInfos(std::vector<std::pair<uint32_t, int32_t>>& vsyncRateInfos)
575 {
576     vsyncRateInfos.clear();
577 
578     std::lock_guard<std::mutex> locker(mutex_);
579     for (auto &connection : connections_) {
580         uint32_t tmpPid;
581         if (QosGetPidByName(connection->info_.name_, tmpPid) != VSYNC_ERROR_OK) {
582             continue;
583         }
584         int32_t tmpRate = connection->highPriorityState_ ? connection->highPriorityRate_ : connection->rate_;
585         vsyncRateInfos.push_back(std::make_pair(tmpPid, tmpRate));
586     }
587     return VSYNC_ERROR_OK;
588 }
589 
ChangeConnsRateLocked()590 void VSyncDistributor::ChangeConnsRateLocked()
591 {
592     std::lock_guard<std::mutex> locker(changingConnsRefreshRatesMtx_);
593     for (auto connRefreshRate : changingConnsRefreshRates_) {
594         for (auto conn : connections_) {
595             if (conn->id_ != connRefreshRate.first) {
596                 continue;
597             }
598             uint32_t refreshRate = connRefreshRate.second;
599             if ((generatorRefreshRate_ == 0) || (refreshRate == 0) ||
600                 (VSYNC_MAX_REFRESHRATE % refreshRate != 0) || (generatorRefreshRate_ % refreshRate != 0)) {
601                 conn->refreshRate_ = 0;
602                 conn->vsyncPulseFreq_ = 1;
603                 continue;
604             }
605             conn->refreshRate_ = refreshRate;
606             conn->vsyncPulseFreq_ = VSYNC_MAX_REFRESHRATE / refreshRate;
607             conn->referencePulseCount_ = event_.vsyncPulseCount;
608         }
609     }
610     changingConnsRefreshRates_.clear();
611 }
612 }
613 }
614