1 /*
2 * Copyright (c) 2021-2024 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 "ui/rs_ui_director.h"
17
18 #include "rs_trace.h"
19 #include "sandbox_utils.h"
20
21 #include "animation/rs_animation_trace_utils.h"
22 #include "command/rs_message_processor.h"
23 #include "command/rs_node_command.h"
24 #include "hyper_graphic_manager/core/utils/hgm_command.h"
25 #include "modifier/rs_modifier_manager.h"
26 #include "modifier/rs_modifier_manager_map.h"
27 #include "pipeline/rs_node_map.h"
28 #include "pipeline/rs_render_thread.h"
29 #include "platform/common/rs_log.h"
30 #include "rs_frame_report.h"
31 #include "transaction/rs_application_agent_impl.h"
32 #include "transaction/rs_interfaces.h"
33 #include "transaction/rs_transaction.h"
34 #include "transaction/rs_transaction_proxy.h"
35 #include "feature/hyper_graphic_manager/rs_frame_rate_policy.h"
36 #include "ui/rs_root_node.h"
37 #include "ui/rs_surface_extractor.h"
38 #include "ui/rs_surface_node.h"
39 #include "ui/rs_ui_context.h"
40 #include "ui/rs_ui_context_manager.h"
41 #ifdef RS_ENABLE_VK
42 #include "modifier_render_thread/rs_modifiers_draw_thread.h"
43 #include "modifier_render_thread/rs_modifiers_draw.h"
44 #endif
45
46 #ifdef _WIN32
47 #include <windows.h>
48 #define gettid GetCurrentThreadId
49 #endif
50
51 #ifdef __APPLE__
52 #define gettid getpid
53 #endif
54
55 #ifdef __gnu_linux__
56 #include <sys/types.h>
57 #include <sys/syscall.h>
58 #define gettid []() -> int32_t { return static_cast<int32_t>(syscall(SYS_gettid)); }
59 #endif
60
61 namespace OHOS {
62 namespace Rosen {
63 std::function<void()> RSUIDirector::requestVsyncCallback_ = nullptr;
64 static std::mutex g_vsyncCallbackMutex;
65 static std::once_flag g_initDumpNodeTreeProcessorFlag;
66 static std::once_flag g_isResidentProcessFlag;
67 static std::once_flag g_initHybridCallback;
68
Create()69 std::shared_ptr<RSUIDirector> RSUIDirector::Create()
70 {
71 return std::shared_ptr<RSUIDirector>(new RSUIDirector());
72 }
73
~RSUIDirector()74 RSUIDirector::~RSUIDirector()
75 {
76 Destroy();
77 }
78
Init(bool shouldCreateRenderThread,bool isMultiInstance)79 void RSUIDirector::Init(bool shouldCreateRenderThread, bool isMultiInstance)
80 {
81 AnimationCommandHelper::SetAnimationCallbackProcessor(AnimationCallbackProcessor);
82 std::call_once(g_initDumpNodeTreeProcessorFlag,
83 []() { RSNodeCommandHelper::SetDumpNodeTreeProcessor(RSUIDirector::DumpNodeTreeProcessor); });
84 if (isMultiInstance) {
85 rsUIContext_ = RSUIContextManager::MutableInstance().CreateRSUIContext();
86 }
87
88 isUniRenderEnabled_ = RSSystemProperties::GetUniRenderEnabled();
89 if (shouldCreateRenderThread && !isUniRenderEnabled_) {
90 auto renderThreadClient = RSIRenderClient::CreateRenderThreadClient();
91 if (rsUIContext_ != nullptr) {
92 auto transaction = rsUIContext_->GetRSTransaction();
93 if (transaction != nullptr) {
94 transaction->SetRenderThreadClient(renderThreadClient);
95 }
96 } else {
97 auto transactionProxy = RSTransactionProxy::GetInstance();
98 if (transactionProxy != nullptr) {
99 transactionProxy->SetRenderThreadClient(renderThreadClient);
100 }
101 }
102
103 RsFrameReport::GetInstance().Init();
104 if (!cacheDir_.empty()) {
105 RSRenderThread::Instance().SetCacheDir(cacheDir_);
106 }
107 RSRenderThread::Instance().Start();
108 } else {
109 // force fallback animaiions send to RS if no render thread
110 RSNodeMap::Instance().GetAnimationFallbackNode()->isRenderServiceNode_ = true;
111 InitHybridRender();
112 }
113 if (!cacheDir_.empty()) {
114 RSRenderThread::Instance().SetCacheDir(cacheDir_);
115 }
116 if (auto rsApplicationAgent = RSApplicationAgentImpl::Instance()) {
117 rsApplicationAgent->RegisterRSApplicationAgent();
118 }
119
120 GoForeground();
121 RSInterpolator::Init();
122 }
123
SetFlushEmptyCallback(FlushEmptyCallback flushEmptyCallback)124 void RSUIDirector::SetFlushEmptyCallback(FlushEmptyCallback flushEmptyCallback)
125 {
126 if (rsUIContext_) {
127 auto transaction = rsUIContext_->GetRSTransaction();
128 if (transaction != nullptr) {
129 transaction->SetFlushEmptyCallback(flushEmptyCallback);
130 }
131 } else {
132 auto transactionProxy = RSTransactionProxy::GetInstance();
133 if (transactionProxy != nullptr) {
134 transactionProxy->SetFlushEmptyCallback(flushEmptyCallback);
135 }
136 }
137 }
138
InitHybridRender()139 void RSUIDirector::InitHybridRender()
140 {
141 #ifdef RS_ENABLE_VK
142 if (RSSystemProperties::GetHybridRenderEnabled()) {
143 CommitTransactionCallback callback =
144 [] (std::shared_ptr<RSIRenderClient> &renderServiceClient,
145 std::unique_ptr<RSTransactionData>&& rsTransactionData, uint32_t& transactionDataIndex,
146 std::shared_ptr<RSTransactionHandler> transactionHandler) {
147 auto task = [renderServiceClient, transactionData = std::move(rsTransactionData),
148 &transactionDataIndex, transactionHandler]() mutable {
149 bool isNeedCommit = true;
150 RSModifiersDrawThread::ConvertTransaction(transactionData, renderServiceClient, isNeedCommit);
151 if (isNeedCommit) {
152 renderServiceClient->CommitTransaction(transactionData);
153 }
154 transactionDataIndex = transactionData->GetIndex();
155 // destroy semaphore after commitTransaction for which syncFence was duped
156 RSModifiersDraw::DestroySemaphore();
157 std::shared_ptr<RSUIContext> rsUICtx;
158 {
159 int32_t instanceId = INSTANCE_ID_UNDEFINED;
160 if (!transactionHandler) {
161 for (auto& [id, _, cmd] : transactionData->GetPayload()) {
162 if (cmd == nullptr) {
163 continue;
164 }
165 if (instanceId == INSTANCE_ID_UNDEFINED) {
166 NodeId realId = id == 0 ? cmd->GetNodeId() : id;
167 instanceId = RSNodeMap::Instance().GetNodeInstanceId(realId);
168 instanceId = (instanceId == INSTANCE_ID_UNDEFINED ?
169 RSNodeMap::Instance().GetInstanceIdForReleasedNode(realId) : instanceId);
170 } else {
171 break;
172 }
173 }
174 }
175 auto dataHolder = std::make_shared<TransactionDataHolder>(std::move(transactionData));
176 std::unique_lock<std::recursive_mutex> lock(RSModifiersDrawThread::transactionDataMutex_);
177 auto task = [dataHolder]() {
178 std::unique_lock<std::recursive_mutex> lock(RSModifiersDrawThread::transactionDataMutex_);
179 (void) dataHolder;
180 };
181 (transactionHandler == nullptr) ? RSUIDirector::PostTask(task, instanceId) :
182 transactionHandler->PostTask(task);
183 }
184 };
185 RSModifiersDrawThread::Instance().ScheduleTask(task);
186 };
187 SetCommitTransactionCallback(callback);
188 }
189 #endif
190 }
191
SetCommitTransactionCallback(CommitTransactionCallback commitTransactionCallback)192 void RSUIDirector::SetCommitTransactionCallback(CommitTransactionCallback commitTransactionCallback)
193 {
194 if (rsUIContext_) {
195 auto transaction = rsUIContext_->GetRSTransaction();
196 if (transaction != nullptr) {
197 std::call_once(g_initHybridCallback, [commitTransactionCallback]() {
198 RSTransactionHandler::SetCommitTransactionCallback(commitTransactionCallback);
199 });
200 }
201 } else {
202 auto transactionProxy = RSTransactionProxy::GetInstance();
203 if (transactionProxy != nullptr) {
204 transactionProxy->SetCommitTransactionCallback(commitTransactionCallback);
205 }
206 }
207 }
208
209 // LCOV_EXCL_START
IsHybridRenderEnabled()210 bool RSUIDirector::IsHybridRenderEnabled()
211 {
212 return RSSystemProperties::GetHybridRenderEnabled();
213 }
214 // LCOV_EXCL_STOP
215
GetHybridRenderSwitch(ComponentEnableSwitch bitSeq)216 bool RSUIDirector::GetHybridRenderSwitch(ComponentEnableSwitch bitSeq)
217 {
218 return RSSystemProperties::GetHybridRenderSwitch(bitSeq);
219 }
220
221 // LCOV_EXCL_START
GetHybridRenderTextBlobLenCount()222 uint32_t RSUIDirector::GetHybridRenderTextBlobLenCount()
223 {
224 return RSSystemProperties::GetHybridRenderTextBlobLenCount();
225 }
226 // LCOV_EXCL_STOP
227
StartTextureExport(std::shared_ptr<RSUIContext> rsUIContext)228 void RSUIDirector::StartTextureExport(std::shared_ptr<RSUIContext> rsUIContext)
229 {
230 isUniRenderEnabled_ = RSSystemProperties::GetUniRenderEnabled();
231 if (isUniRenderEnabled_) {
232 auto renderThreadClient = RSIRenderClient::CreateRenderThreadClient();
233 if (rsUIContext) {
234 auto transaction = rsUIContext->GetRSTransaction();
235 if (transaction != nullptr) {
236 transaction->SetRenderThreadClient(renderThreadClient);
237 }
238 } else {
239 auto transactionProxy = RSTransactionProxy::GetInstance();
240 if (transactionProxy != nullptr) {
241 transactionProxy->SetRenderThreadClient(renderThreadClient);
242 }
243 }
244 RSRenderThread::Instance().Start();
245 }
246 RSRenderThread::Instance().UpdateWindowStatus(true);
247 }
248
GoForeground(bool isTextureExport)249 void RSUIDirector::GoForeground(bool isTextureExport)
250 {
251 ROSEN_LOGD("RSUIDirector::GoForeground");
252 if (!isActive_) {
253 auto nowTime = std::chrono::system_clock::now().time_since_epoch();
254 lastUiSkipTimestamp_ = std::chrono::duration_cast<std::chrono::milliseconds>(nowTime).count();
255 if (!isUniRenderEnabled_ || isTextureExport) {
256 RSRenderThread::Instance().UpdateWindowStatus(true);
257 }
258 isActive_ = true;
259 auto node = rootNode_.lock();
260 if (node) {
261 node->SetEnableRender(true);
262 }
263 auto surfaceNode = surfaceNode_.lock();
264 if (surfaceNode) {
265 surfaceNode->MarkUIHidden(false);
266 surfaceNode->SetAbilityState(RSSurfaceNodeAbilityState::FOREGROUND);
267 }
268 }
269 #ifdef RS_ENABLE_VK
270 RSModifiersDraw::InsertForegroundRoot(root_);
271 #endif
272 }
273
ReportUiSkipEvent(const std::string & abilityName)274 void RSUIDirector::ReportUiSkipEvent(const std::string& abilityName)
275 {
276 auto nowTime = std::chrono::system_clock::now().time_since_epoch();
277 int64_t nowMs = std::chrono::duration_cast<std::chrono::milliseconds>(nowTime).count();
278 auto transactionProxy = RSTransactionProxy::GetInstance();
279 if (transactionProxy != nullptr) {
280 transactionProxy->ReportUiSkipEvent(abilityName, nowMs, lastUiSkipTimestamp_);
281 }
282 }
283
GoBackground(bool isTextureExport)284 void RSUIDirector::GoBackground(bool isTextureExport)
285 {
286 ROSEN_LOGD("RSUIDirector::GoBackground");
287 if (isActive_) {
288 if (!isUniRenderEnabled_ || isTextureExport) {
289 RSRenderThread::Instance().UpdateWindowStatus(false);
290 }
291 isActive_ = false;
292 ReportUiSkipEvent(abilityName_);
293 auto node = rootNode_.lock();
294 if (node) {
295 node->SetEnableRender(false);
296 }
297 auto surfaceNode = surfaceNode_.lock();
298 if (surfaceNode) {
299 surfaceNode->MarkUIHidden(true);
300 surfaceNode->SetAbilityState(RSSurfaceNodeAbilityState::BACKGROUND);
301 }
302 if (isTextureExport || isUniRenderEnabled_) {
303 #ifdef RS_ENABLE_VK
304 RSModifiersDraw::EraseForegroundRoot(root_);
305 #endif
306 return;
307 }
308 // clean bufferQueue cache
309 RSRenderThread::Instance().PostTask([surfaceNode]() {
310 if (surfaceNode != nullptr) {
311 std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
312 if (rsSurface == nullptr) {
313 ROSEN_LOGE("rsSurface is nullptr");
314 #ifdef RS_ENABLE_VK
315 RSModifiersDraw::EraseForegroundRoot(root_);
316 #endif
317 return;
318 }
319 rsSurface->ClearBuffer();
320 }
321 });
322 #if defined(ACE_ENABLE_GL) || defined(ACE_ENABLE_VK)
323 RSRenderThread::Instance().PostTask([this]() {
324 auto renderContext = RSRenderThread::Instance().GetRenderContext();
325 if (renderContext != nullptr) {
326 #ifndef ROSEN_CROSS_PLATFORM
327 renderContext->ClearRedundantResources();
328 #endif
329 }
330 });
331 #endif
332 }
333 #ifdef RS_ENABLE_VK
334 RSModifiersDraw::EraseForegroundRoot(root_);
335 #endif
336 }
337
Destroy(bool isTextureExport)338 void RSUIDirector::Destroy(bool isTextureExport)
339 {
340 if (auto node = rootNode_.lock()) {
341 if (!isUniRenderEnabled_ || isTextureExport) {
342 node->RemoveFromTree();
343 }
344 rootNode_.reset();
345 }
346 GoBackground(isTextureExport);
347 if (rsUIContext_ != nullptr) {
348 RSUIContextManager::MutableInstance().DestroyContext(rsUIContext_->GetToken());
349 rsUIContext_ = nullptr;
350 }
351 std::unique_lock<std::mutex> lock(uiTaskRunnersVisitorMutex_);
352 uiTaskRunners_.erase(this); // to del
353 }
354
SetRSSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode)355 void RSUIDirector::SetRSSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode)
356 {
357 surfaceNode_ = surfaceNode;
358 AttachSurface();
359 }
360
GetRSSurfaceNode() const361 std::shared_ptr<RSSurfaceNode> RSUIDirector::GetRSSurfaceNode() const
362 {
363 return surfaceNode_.lock();
364 }
365
SetAbilityBGAlpha(uint8_t alpha)366 void RSUIDirector::SetAbilityBGAlpha(uint8_t alpha)
367 {
368 auto node = surfaceNode_.lock();
369 if (!node) {
370 ROSEN_LOGI("RSUIDirector::SetAbilityBGAlpha, surfaceNode_ is nullptr");
371 return;
372 }
373 node->SetAbilityBGAlpha(alpha);
374 }
375
SetRTRenderForced(bool isRenderForced)376 void RSUIDirector::SetRTRenderForced(bool isRenderForced)
377 {
378 RSRenderThread::Instance().SetRTRenderForced(isRenderForced);
379 }
380
SetContainerWindow(bool hasContainerWindow,RRect rrect)381 void RSUIDirector::SetContainerWindow(bool hasContainerWindow, RRect rrect)
382 {
383 auto node = surfaceNode_.lock();
384 if (!node) {
385 ROSEN_LOGI("RSUIDirector::SetContainerWindow, surfaceNode_ is nullptr");
386 return;
387 }
388 node->SetContainerWindow(hasContainerWindow, rrect);
389 }
390
SetRoot(NodeId root)391 void RSUIDirector::SetRoot(NodeId root)
392 {
393 if (root_ == root) {
394 ROSEN_LOGW("RSUIDirector::SetRoot, root_ is not change");
395 return;
396 }
397 root_ = root;
398 AttachSurface();
399 }
400
AttachSurface()401 void RSUIDirector::AttachSurface()
402 {
403 auto surfaceNode = surfaceNode_.lock();
404 auto node = rootNode_.lock();
405 if (node != nullptr && surfaceNode != nullptr) {
406 node->AttachRSSurfaceNode(surfaceNode);
407 ROSEN_LOGD("RSUIDirector::AttachSurface [%{public}" PRIu64, surfaceNode->GetId());
408 } else {
409 ROSEN_LOGD("RSUIDirector::AttachSurface not ready");
410 }
411 }
412
SetRSRootNode(std::shared_ptr<RSRootNode> rootNode)413 void RSUIDirector::SetRSRootNode(std::shared_ptr<RSRootNode> rootNode)
414 {
415 if (rootNode_.lock() == rootNode) {
416 return;
417 }
418 rootNode_ = rootNode;
419 AttachSurface();
420 }
421
SetAppFreeze(bool isAppFreeze)422 void RSUIDirector::SetAppFreeze(bool isAppFreeze)
423 {
424 auto surfaceNode = surfaceNode_.lock();
425 if (surfaceNode != nullptr) {
426 surfaceNode->SetFreeze(isAppFreeze);
427 }
428 }
429
SetRequestVsyncCallback(const std::function<void ()> & callback)430 void RSUIDirector::SetRequestVsyncCallback(const std::function<void()>& callback)
431 {
432 std::unique_lock<std::mutex> lock(g_vsyncCallbackMutex);
433 requestVsyncCallback_ = callback;
434 }
435
SetTimeStamp(uint64_t timeStamp,const std::string & abilityName)436 void RSUIDirector::SetTimeStamp(uint64_t timeStamp, const std::string& abilityName)
437 {
438 timeStamp_ = timeStamp;
439 abilityName_ = abilityName;
440 dvsyncUpdate_ = false;
441 }
442
SetDVSyncUpdate(uint64_t dvsyncTime)443 void RSUIDirector::SetDVSyncUpdate(uint64_t dvsyncTime)
444 {
445 dvsyncUpdate_ = true;
446 dvsyncTime_ = dvsyncTime;
447 }
448
SetCacheDir(const std::string & cacheFilePath)449 void RSUIDirector::SetCacheDir(const std::string& cacheFilePath)
450 {
451 cacheDir_ = cacheFilePath;
452 #ifdef RS_ENABLE_VK
453 if (!cacheDir_.empty() && RSSystemProperties::GetHybridRenderEnabled()) {
454 RSModifiersDrawThread::Instance().SetCacheDir(cacheDir_);
455 }
456 #endif
457 }
458
FlushAnimation(uint64_t timeStamp,int64_t vsyncPeriod)459 bool RSUIDirector::FlushAnimation(uint64_t timeStamp, int64_t vsyncPeriod)
460 {
461 auto rsUIContext = rsUIContext_;
462 auto modifierManager = rsUIContext ? rsUIContext->GetRSModifierManager()
463 : RSModifierManagerMap::Instance()->GetModifierManager(gettid());
464 if (modifierManager != nullptr) {
465 modifierManager->SetDisplaySyncEnable(true);
466 modifierManager->SetFrameRateGetFunc(
467 [](const RSPropertyUnit unit, float velocity, int32_t area, int length) -> int32_t {
468 return RSFrameRatePolicy::GetInstance()->GetExpectedFrameRate(unit, velocity);
469 }
470 );
471 return modifierManager->Animate(timeStamp, vsyncPeriod);
472 }
473 return false;
474 }
475
HasFirstFrameAnimation()476 bool RSUIDirector::HasFirstFrameAnimation()
477 {
478 auto rsUIContext = rsUIContext_;
479 auto modifierManager = rsUIContext ? rsUIContext->GetRSModifierManager()
480 : RSModifierManagerMap::Instance()->GetModifierManager(gettid());
481 if (modifierManager != nullptr) {
482 return modifierManager->GetAndResetFirstFrameAnimationState();
483 }
484 return false;
485 }
486
FlushAnimationStartTime(uint64_t timeStamp)487 void RSUIDirector::FlushAnimationStartTime(uint64_t timeStamp)
488 {
489 auto rsUIContext = rsUIContext_;
490 auto modifierManager = rsUIContext ? rsUIContext->GetRSModifierManager()
491 : RSModifierManagerMap::Instance()->GetModifierManager(gettid());
492 if (modifierManager != nullptr) {
493 modifierManager->FlushStartAnimation(timeStamp);
494 }
495 }
496
FlushModifier()497 void RSUIDirector::FlushModifier()
498 {
499 std::shared_ptr<RSModifierManager> modifierManager = nullptr;
500 if (rsUIContext_ == nullptr) {
501 modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
502 } else {
503 modifierManager = rsUIContext_->GetRSModifierManager();
504 }
505 if (modifierManager == nullptr) {
506 return;
507 }
508
509 modifierManager->Draw();
510 // post animation finish callback(s) to task queue
511 RSUIDirector::RecvMessages();
512 }
513
HasUIRunningAnimation()514 bool RSUIDirector::HasUIRunningAnimation()
515 {
516 auto rsUIContext = rsUIContext_;
517 auto modifierManager = rsUIContext ? rsUIContext->GetRSModifierManager()
518 : RSModifierManagerMap::Instance()->GetModifierManager(gettid());
519 if (modifierManager != nullptr) {
520 return modifierManager->HasUIRunningAnimation();
521 }
522 return false;
523 }
524
SetUITaskRunner(const TaskRunner & uiTaskRunner,int32_t instanceId,bool useMultiInstance)525 void RSUIDirector::SetUITaskRunner(const TaskRunner& uiTaskRunner, int32_t instanceId, bool useMultiInstance)
526 {
527 if (!useMultiInstance) {
528 std::unique_lock<std::mutex> lock(uiTaskRunnersVisitorMutex_);
529 instanceId_ = instanceId;
530 uiTaskRunners_[this] = uiTaskRunner;
531 if (!isHgmConfigChangeCallbackReg_) {
532 RSFrameRatePolicy::GetInstance()->RegisterHgmConfigChangeCallback();
533 isHgmConfigChangeCallbackReg_ = true;
534 }
535 return;
536 }
537
538 if (rsUIContext_ == nullptr) {
539 ROSEN_LOGD("multi-instance, RSUIDirector::SetUITaskRunner, rsUIContext_ is null!");
540 return;
541 }
542 if (!isHgmConfigChangeCallbackReg_) {
543 RSFrameRatePolicy::GetInstance()->RegisterHgmConfigChangeCallback();
544 isHgmConfigChangeCallbackReg_ = true;
545 }
546 }
547
SendMessages()548 void RSUIDirector::SendMessages()
549 {
550 if (rsUIContext_) {
551 RS_TRACE_NAME_FMT("SendCommands, rsUIContext_:%lu", rsUIContext_->GetToken());
552 auto transaction = rsUIContext_->GetRSTransaction();
553 if (transaction != nullptr) {
554 transaction->FlushImplicitTransaction(timeStamp_, abilityName_, dvsyncUpdate_, dvsyncTime_);
555 index_ = transaction->GetTransactionDataIndex();
556 } else {
557 RS_LOGE_LIMIT(__func__, __line__, "RSUIDirector::SendMessages failed, transaction is nullptr");
558 }
559 } else {
560 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "SendCommands");
561 auto transactionProxy = RSTransactionProxy::GetInstance();
562 if (transactionProxy != nullptr) {
563 transactionProxy->FlushImplicitTransaction(timeStamp_, abilityName_, dvsyncUpdate_, dvsyncTime_);
564 index_ = transactionProxy->GetTransactionDataIndex();
565 } else {
566 RS_LOGE_LIMIT(__func__, __line__, "RSUIDirector::SendMessages failed, transactionProxy is nullptr");
567 }
568 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
569 }
570 }
571
SendMessages(std::function<void ()> callback)572 void RSUIDirector::SendMessages(std::function<void()> callback)
573 {
574 if (rsUIContext_) {
575 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "multi-intance SendCommands With Callback");
576 RS_TRACE_NAME_FMT("multi-instance SendCommands, rsUIContext_:%lu", rsUIContext_->GetToken());
577 auto transaction = rsUIContext_->GetRSTransaction();
578 if (transaction != nullptr && !transaction->IsEmpty()) {
579 if (callback != nullptr) {
580 RS_LOGD("RSUIDirector:: multi-intance SendMessages with callback, timeStamp: %{public}"
581 PRIu64 " token: %{public}" PRIu64, timeStamp_, rsUIContext_->GetToken());
582 RSInterfaces::GetInstance().RegisterTransactionDataCallback(rsUIContext_->GetToken(),
583 timeStamp_, callback);
584 }
585 transaction->FlushImplicitTransaction(timeStamp_, abilityName_, dvsyncUpdate_, dvsyncTime_);
586 index_ = transaction->GetTransactionDataIndex();
587 } else {
588 RS_LOGE_LIMIT(__func__, __line__, "RSUIDirector:: multi-intance SendMessages failed, \
589 transaction is nullptr");
590 }
591 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
592 } else {
593 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "SendCommands With Callback");
594 auto transactionProxy = RSTransactionProxy::GetInstance();
595 if (transactionProxy != nullptr && !transactionProxy->IsEmpty()) {
596 if (callback != nullptr) {
597 static const uint64_t pid = static_cast<uint64_t>(getpid());
598 RS_LOGD("RSUIDirector::SendMessages with callback, timeStamp: %{public}"
599 PRIu64 " pid: %{public}" PRIu64, timeStamp_, pid);
600 RSInterfaces::GetInstance().RegisterTransactionDataCallback(pid, timeStamp_, callback);
601 }
602 transactionProxy->FlushImplicitTransaction(timeStamp_, abilityName_, dvsyncUpdate_, dvsyncTime_);
603 index_ = transactionProxy->GetTransactionDataIndex();
604 } else {
605 RS_LOGE_LIMIT(__func__, __line__, "RSUIDirector::SendMessages failed, transactionProxy is nullptr");
606 }
607 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
608 }
609 }
610
GetIndex() const611 uint32_t RSUIDirector::GetIndex() const
612 {
613 return index_;
614 }
615
GetRSUIContext() const616 std::shared_ptr<RSUIContext> RSUIDirector::GetRSUIContext() const
617 {
618 return rsUIContext_;
619 }
620
RecvMessages()621 void RSUIDirector::RecvMessages()
622 {
623 if (GetRealPid() == -1) {
624 return;
625 }
626 static const uint32_t pid = static_cast<uint32_t>(GetRealPid());
627 if (!RSMessageProcessor::Instance().HasTransaction(pid)) {
628 return;
629 }
630 auto transactionDataPtr = RSMessageProcessor::Instance().GetTransaction(pid);
631 RecvMessages(transactionDataPtr);
632 }
633
RecvMessages(std::shared_ptr<RSTransactionData> cmds)634 void RSUIDirector::RecvMessages(std::shared_ptr<RSTransactionData> cmds)
635 {
636 if (cmds == nullptr || cmds->IsEmpty()) {
637 ROSEN_LOGD("RSUIDirector::RecvMessages cmd empty");
638 return;
639 }
640 ROSEN_LOGD("ProcessMessages begin");
641 RSUIDirector::ProcessMessages(cmds);
642 }
643
ProcessInstanceMessages(std::map<int32_t,std::vector<std::unique_ptr<RSCommand>>> & cmdMap,uint32_t messageId)644 void RSUIDirector::ProcessInstanceMessages(
645 std::map<int32_t, std::vector<std::unique_ptr<RSCommand>>>& cmdMap, uint32_t messageId)
646 {
647 auto counter = std::make_shared<std::atomic_size_t>(cmdMap.size());
648 for (auto& [instanceId, commands] : cmdMap) {
649 ROSEN_LOGD("Post messageId:%{public}d, cmdCount:%{public}lu, instanceId:%{public}d", messageId,
650 static_cast<unsigned long>(commands.size()), instanceId);
651 PostTask(
652 [cmds = std::make_shared<std::vector<std::unique_ptr<RSCommand>>>(std::move(commands)), counter, messageId,
653 tempInstanceId = instanceId] {
654 RS_TRACE_NAME_FMT("RSUIDirector::ProcessInstanceMessages Process messageId:%lu", messageId);
655 ROSEN_LOGD("Process messageId:%{public}d, cmdCount:%{public}lu, instanceId:%{public}d", messageId,
656 static_cast<unsigned long>(cmds->size()), tempInstanceId);
657 for (auto& cmd : *cmds) {
658 RSContext context; // RSCommand->process() needs it
659 cmd->Process(context);
660 }
661 if (counter->fetch_sub(1) == 1) {
662 std::unique_lock<std::mutex> lock(g_vsyncCallbackMutex);
663 if (requestVsyncCallback_ != nullptr) {
664 requestVsyncCallback_();
665 } else {
666 RSTransaction::FlushImplicitTransaction();
667 }
668 ROSEN_LOGD("ProcessInstanceMessages end");
669 }
670 },
671 instanceId);
672 }
673 }
674
ProcessUIContextMessages(std::map<uint64_t,std::vector<std::unique_ptr<RSCommand>>> & cmdMap,uint32_t messageId)675 void RSUIDirector::ProcessUIContextMessages(
676 std::map<uint64_t, std::vector<std::unique_ptr<RSCommand>>>& cmdMap, uint32_t messageId)
677 {
678 auto counter = std::make_shared<std::atomic_size_t>(cmdMap.size());
679 for (auto& [token, commands] : cmdMap) {
680 ROSEN_LOGD("Post messageId:%{public}d, cmdCount:%{public}lu, token:%{public}" PRIu64, messageId,
681 static_cast<unsigned long>(commands.size()), token);
682 auto rsUICtx = RSUIContextManager::Instance().GetRSUIContext(token);
683 if (rsUICtx == nullptr) {
684 ROSEN_LOGI(
685 "RSUIDirector::ProcessUIContextMessages, can not get rsUIContext with token:%{public}" PRIu64, token);
686 continue;
687 }
688 rsUICtx->PostTask([cmds = std::make_shared<std::vector<std::unique_ptr<RSCommand>>>(std::move(commands)),
689 counter, messageId, tempToken = token, rsUICtx] {
690 RS_TRACE_NAME_FMT("RSUIDirector::ProcessUIContextMessages Process messageId:%lu", messageId);
691 ROSEN_LOGD("Process messageId:%{public}d, cmdCount:%{public}lu, token:%{public}" PRIu64, messageId,
692 static_cast<unsigned long>(cmds->size()), tempToken);
693 for (auto& cmd : *cmds) {
694 RSContext context; // RSCommand->process() needs it
695 cmd->Process(context);
696 }
697 if (counter->fetch_sub(1) == 1) {
698 std::unique_lock<std::mutex> lock(g_vsyncCallbackMutex);
699 if (requestVsyncCallback_ != nullptr) {
700 requestVsyncCallback_();
701 } else {
702 auto rsTransaction = rsUICtx->GetRSTransaction();
703 if (rsTransaction != nullptr) {
704 rsTransaction->FlushImplicitTransaction();
705 }
706 }
707 ROSEN_LOGD("ProcessUIContextMessages end");
708 }
709 });
710 }
711 }
712
ProcessMessages(std::shared_ptr<RSTransactionData> cmds)713 void RSUIDirector::ProcessMessages(std::shared_ptr<RSTransactionData> cmds)
714 {
715 // message ID for correspondence UI thread and IPC thread
716 static uint32_t messageId = 0;
717 std::map<int32_t, std::vector<std::unique_ptr<RSCommand>>> instanceCmdMap;
718 std::map<uint64_t, std::vector<std::unique_ptr<RSCommand>>> uiContextCmdMap;
719 for (auto& [id, _, cmd] : cmds->GetPayload()) {
720 uint64_t token = cmd->GetToken();
721 if (token == 0) {
722 NodeId realId = (id == 0 && cmd) ? cmd->GetNodeId() : id;
723 int32_t instanceId = RSNodeMap::Instance().GetNodeInstanceId(realId);
724 if (instanceId == INSTANCE_ID_UNDEFINED) {
725 instanceId = RSNodeMap::Instance().GetInstanceIdForReleasedNode(realId);
726 }
727 instanceCmdMap[instanceId].push_back(std::move(cmd));
728 } else {
729 uiContextCmdMap[token].push_back(std::move(cmd));
730 }
731 }
732 auto msgId = ++messageId;
733 RS_TRACE_NAME_FMT("RSUIDirector::ProcessMessages Post [messageId:%lu,cmdIndex:%llu,cmdCount:%lu]", msgId,
734 cmds->GetIndex(), cmds->GetCommandCount());
735 ProcessInstanceMessages(instanceCmdMap, msgId);
736 ProcessUIContextMessages(uiContextCmdMap, msgId);
737 }
738
AnimationCallbackProcessor(NodeId nodeId,AnimationId animId,uint64_t token,AnimationCallbackEvent event)739 void RSUIDirector::AnimationCallbackProcessor(NodeId nodeId, AnimationId animId, uint64_t token,
740 AnimationCallbackEvent event)
741 {
742 RSAnimationTraceUtils::GetInstance().AddAnimationFinishTrace(
743 "Animation FinishCallback Processor", nodeId, animId, false);
744 auto rsUIContext = RSUIContextManager::Instance().GetRSUIContext(token);
745 // try find the node by nodeId
746 if (auto nodePtr = rsUIContext ? rsUIContext->GetNodeMap().GetNode<RSNode>(nodeId)
747 : RSNodeMap::Instance().GetNode<RSNode>(nodeId)) {
748 if (!nodePtr->AnimationCallback(animId, event)) {
749 ROSEN_LOGE("RSUIDirector::AnimationCallbackProcessor, could not find animation %{public}" PRIu64 ""
750 "on node %{public}" PRIu64, animId, nodeId);
751 }
752 return;
753 }
754
755 // if node not found, try rsUIContext
756 if (rsUIContext && rsUIContext->AnimationCallback(animId, event)) {
757 ROSEN_LOGD("multi-instance, RSUIDirector::AnimationCallbackProcessor, found animation %{public}" PRIu64
758 " on fallback node.", animId);
759 return;
760 }
761 // if node not found, try fallback node
762 auto& fallbackNode = RSNodeMap::Instance().GetAnimationFallbackNode();
763 if (fallbackNode && fallbackNode->AnimationCallback(animId, event)) {
764 ROSEN_LOGD("RSUIDirector::AnimationCallbackProcessor, found animation %{public}" PRIu64 " on fallback node.",
765 animId);
766 } else {
767 ROSEN_LOGE("RSUIDirector::AnimationCallbackProcessor, could not find animation %{public}" PRIu64 " on"
768 " fallback node.", animId);
769 }
770 }
771
DumpNodeTreeProcessor(NodeId nodeId,pid_t pid,uint64_t token,uint32_t taskId)772 void RSUIDirector::DumpNodeTreeProcessor(NodeId nodeId, pid_t pid, uint64_t token, uint32_t taskId)
773 {
774 RS_TRACE_NAME_FMT("DumpClientNodeTree dump task[%u] node[%" PRIu64 "]", taskId, nodeId);
775 ROSEN_LOGI("DumpNodeTreeProcessor task[%{public}u] node[%" PRIu64 "]", taskId, nodeId);
776
777 std::string out;
778 // use for dump transactionFlags [pid,index] in client tree dump
779 if (auto rsUICtx = RSUIContextManager::Instance().GetRSUIContext(token)) {
780 rsUICtx->DumpNodeTreeProcessor(nodeId, pid, taskId, out);
781 return;
782 }
783 int32_t instanceId = RSNodeMap::Instance().GetNodeInstanceId(nodeId);
784 {
785 std::unique_lock<std::mutex> lock(uiTaskRunnersVisitorMutex_);
786 for (const auto &[director, taskRunner] : uiTaskRunners_) {
787 if (director->instanceId_ == instanceId) {
788 out.append("transactionFlags:[ ").append(std::to_string(pid).append(", ")
789 .append(std::to_string(director->index_)).append("]\r"));
790 break;
791 }
792 }
793 }
794
795 if (auto node = RSNodeMap::Instance().GetNode(nodeId)) {
796 constexpr int TOP_LEVEL_DEPTH = 1;
797 node->DumpTree(TOP_LEVEL_DEPTH, out);
798 }
799
800 auto transactionProxy = RSTransactionProxy::GetInstance(); // planing
801 if (transactionProxy != nullptr) {
802 std::unique_ptr<RSCommand> command = std::make_unique<RSCommitDumpClientNodeTree>(
803 nodeId, getpid(), taskId, out);
804 transactionProxy->AddCommand(command, true);
805 RSTransaction::FlushImplicitTransaction();
806 }
807 }
808
PostFrameRateTask(const std::function<void ()> & task,bool useMultiInstance)809 void RSUIDirector::PostFrameRateTask(const std::function<void()>& task, bool useMultiInstance)
810 {
811 if (!useMultiInstance) {
812 PostTask(task);
813 return;
814 }
815 auto ctx = RSUIContextManager::Instance().GetRandomUITaskRunnerCtx();
816 if (ctx == nullptr) {
817 ROSEN_LOGD("multi-instance RSUIDirector::PostFrameRateTask, no taskRunner exists");
818 return;
819 }
820 ctx->PostTask(task);
821 }
822
PostTask(const std::function<void ()> & task,int32_t instanceId)823 void RSUIDirector::PostTask(const std::function<void()>& task, int32_t instanceId)
824 {
825 PostDelayTask(task, 0, instanceId);
826 }
827
PostDelayTask(const std::function<void ()> & task,uint32_t delay,int32_t instanceId)828 void RSUIDirector::PostDelayTask(const std::function<void()>& task, uint32_t delay, int32_t instanceId)
829 {
830 std::unique_lock<std::mutex> lock(uiTaskRunnersVisitorMutex_);
831 for (const auto &[director, taskRunner] : uiTaskRunners_) {
832 if (director->instanceId_ != instanceId) {
833 continue;
834 }
835 ROSEN_LOGD("RSUIDirector::PostTask instanceId=%{public}d success", instanceId);
836 taskRunner(task, delay);
837 return;
838 }
839 if (instanceId != INSTANCE_ID_UNDEFINED) {
840 ROSEN_LOGW("RSUIDirector::PostTask instanceId=%{public}d not found, taskRunnerSize=%{public}zu", instanceId,
841 uiTaskRunners_.size());
842 }
843 for (const auto &[_, taskRunner] : uiTaskRunners_) {
844 ROSEN_LOGD("RSUIDirector::PostTask success");
845 taskRunner(task, delay);
846 return;
847 }
848 }
849
GetCurrentRefreshRateMode()850 int32_t RSUIDirector::GetCurrentRefreshRateMode()
851 {
852 return RSFrameRatePolicy::GetInstance()->GetRefreshRateModeName();
853 }
854
GetAnimateExpectedRate() const855 int32_t RSUIDirector::GetAnimateExpectedRate() const
856 {
857 int32_t animateRate = 0;
858 auto modifierManager = rsUIContext_ ? rsUIContext_->GetRSModifierManager()
859 : RSModifierManagerMap::Instance()->GetModifierManager(gettid());
860 if (modifierManager != nullptr) {
861 auto& range = modifierManager->GetFrameRateRange();
862 if (range.IsValid()) {
863 animateRate = range.preferred_;
864 }
865 }
866 return animateRate;
867 }
868
SetTypicalResidentProcessOnce(bool isTypicalResidentProcess)869 void RSUIDirector::SetTypicalResidentProcessOnce(bool isTypicalResidentProcess)
870 {
871 std::call_once(g_isResidentProcessFlag,
872 [isTypicalResidentProcess]() { RSSystemProperties::SetTypicalResidentProcess(isTypicalResidentProcess); });
873 }
874
SetTypicalResidentProcess(bool isTypicalResidentProcess)875 void RSUIDirector::SetTypicalResidentProcess(bool isTypicalResidentProcess)
876 {
877 SetTypicalResidentProcessOnce(isTypicalResidentProcess);
878 }
879 } // namespace Rosen
880 } // namespace OHOS
881