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, ¶m);
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