• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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