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 "ui/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 #ifdef NEW_RENDER_CONTEXT
40 #include "render_context/memory_handler.h"
41 #endif
42 
43 #ifdef _WIN32
44 #include <windows.h>
45 #define gettid GetCurrentThreadId
46 #endif
47 
48 #ifdef __APPLE__
49 #define gettid getpid
50 #endif
51 
52 #ifdef __gnu_linux__
53 #include <sys/types.h>
54 #include <sys/syscall.h>
55 #define gettid []() -> int32_t { return static_cast<int32_t>(syscall(SYS_gettid)); }
56 #endif
57 
58 namespace OHOS {
59 namespace Rosen {
60 static std::unordered_map<RSUIDirector*, TaskRunner> g_uiTaskRunners;
61 static std::mutex g_uiTaskRunnersVisitorMutex;
62 std::function<void()> RSUIDirector::requestVsyncCallback_ = nullptr;
63 static std::mutex g_vsyncCallbackMutex;
64 static std::once_flag g_initDumpNodeTreeProcessorFlag;
65 
Create()66 std::shared_ptr<RSUIDirector> RSUIDirector::Create()
67 {
68     return std::shared_ptr<RSUIDirector>(new RSUIDirector());
69 }
70 
~RSUIDirector()71 RSUIDirector::~RSUIDirector()
72 {
73     Destroy();
74 }
75 
Init(bool shouldCreateRenderThread)76 void RSUIDirector::Init(bool shouldCreateRenderThread)
77 {
78     AnimationCommandHelper::SetAnimationCallbackProcessor(AnimationCallbackProcessor);
79     std::call_once(g_initDumpNodeTreeProcessorFlag, [] () {
80         RSNodeCommandHelper::SetDumpNodeTreeProcessor(RSUIDirector::DumpNodeTreeProcessor);
81     });
82 
83     isUniRenderEnabled_ = RSSystemProperties::GetUniRenderEnabled();
84     if (shouldCreateRenderThread && !isUniRenderEnabled_) {
85         auto renderThreadClient = RSIRenderClient::CreateRenderThreadClient();
86         auto transactionProxy = RSTransactionProxy::GetInstance();
87         if (transactionProxy != nullptr) {
88             transactionProxy->SetRenderThreadClient(renderThreadClient);
89         }
90 
91         RsFrameReport::GetInstance().Init();
92         if (!cacheDir_.empty()) {
93             RSRenderThread::Instance().SetCacheDir(cacheDir_);
94         }
95         RSRenderThread::Instance().Start();
96     } else {
97         // force fallback animaiions send to RS if no render thread
98         RSNodeMap::Instance().GetAnimationFallbackNode()->isRenderServiceNode_ = true;
99     }
100     if (auto rsApplicationAgent = RSApplicationAgentImpl::Instance()) {
101         rsApplicationAgent->RegisterRSApplicationAgent();
102     }
103 
104     GoForeground();
105     RSInterpolator::Init();
106 }
107 
SetFlushEmptyCallback(FlushEmptyCallback flushEmptyCallback)108 void RSUIDirector::SetFlushEmptyCallback(FlushEmptyCallback flushEmptyCallback)
109 {
110     auto transactionProxy = RSTransactionProxy::GetInstance();
111     if (transactionProxy != nullptr) {
112         transactionProxy->SetFlushEmptyCallback(flushEmptyCallback);
113     }
114 }
115 
StartTextureExport()116 void RSUIDirector::StartTextureExport()
117 {
118     isUniRenderEnabled_ = RSSystemProperties::GetUniRenderEnabled();
119     if (isUniRenderEnabled_) {
120         auto renderThreadClient = RSIRenderClient::CreateRenderThreadClient();
121         auto transactionProxy = RSTransactionProxy::GetInstance();
122         if (transactionProxy != nullptr) {
123             transactionProxy->SetRenderThreadClient(renderThreadClient);
124         }
125         RSRenderThread::Instance().Start();
126     }
127     RSRenderThread::Instance().UpdateWindowStatus(true);
128 }
129 
GoForeground(bool isTextureExport)130 void RSUIDirector::GoForeground(bool isTextureExport)
131 {
132     ROSEN_LOGD("RSUIDirector::GoForeground");
133     if (!isActive_) {
134         if (!isUniRenderEnabled_ || isTextureExport) {
135             RSRenderThread::Instance().UpdateWindowStatus(true);
136         }
137         isActive_ = true;
138         if (auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_)) {
139             node->SetEnableRender(true);
140         }
141         auto surfaceNode = surfaceNode_.lock();
142         if (surfaceNode) {
143             surfaceNode->MarkUIHidden(false);
144             surfaceNode->SetAbilityState(RSSurfaceNodeAbilityState::FOREGROUND);
145         }
146     }
147 }
148 
GoBackground(bool isTextureExport)149 void RSUIDirector::GoBackground(bool isTextureExport)
150 {
151     ROSEN_LOGD("RSUIDirector::GoBackground");
152     if (isActive_) {
153         if (!isUniRenderEnabled_ || isTextureExport) {
154             RSRenderThread::Instance().UpdateWindowStatus(false);
155         }
156         isActive_ = false;
157         if (auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_)) {
158             node->SetEnableRender(false);
159         }
160         auto surfaceNode = surfaceNode_.lock();
161         if (surfaceNode) {
162             surfaceNode->MarkUIHidden(true);
163             surfaceNode->SetAbilityState(RSSurfaceNodeAbilityState::BACKGROUND);
164         }
165         if (isTextureExport || isUniRenderEnabled_) {
166             return;
167         }
168         // clean bufferQueue cache
169         RSRenderThread::Instance().PostTask([surfaceNode]() {
170             if (surfaceNode != nullptr) {
171 #ifdef NEW_RENDER_CONTEXT
172                 std::shared_ptr<RSRenderSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
173 #else
174                 std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
175 #endif
176                 if (rsSurface == nullptr) {
177                     ROSEN_LOGE("rsSurface is nullptr");
178                     return;
179                 }
180                 rsSurface->ClearBuffer();
181             }
182         });
183 #if defined(ACE_ENABLE_GL) || defined(ACE_ENABLE_VK)
184         RSRenderThread::Instance().PostTask([this]() {
185             auto renderContext = RSRenderThread::Instance().GetRenderContext();
186             if (renderContext != nullptr) {
187 #ifndef ROSEN_CROSS_PLATFORM
188 #if defined(NEW_RENDER_CONTEXT)
189                 auto drawingContext = RSRenderThread::Instance().GetDrawingContext();
190                 MemoryHandler::ClearRedundantResources(drawingContext->GetDrawingContext());
191 #else
192                 renderContext->ClearRedundantResources();
193 #endif
194 #endif
195             }
196         });
197 #endif
198     }
199 }
200 
Destroy(bool isTextureExport)201 void RSUIDirector::Destroy(bool isTextureExport)
202 {
203     if (root_ != 0) {
204         if (!isUniRenderEnabled_ || isTextureExport) {
205             if (auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_)) {
206                 node->RemoveFromTree();
207             }
208         }
209         root_ = 0;
210     }
211     GoBackground(isTextureExport);
212     std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
213     g_uiTaskRunners.erase(this);
214 }
215 
SetRSSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode)216 void RSUIDirector::SetRSSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode)
217 {
218     surfaceNode_ = surfaceNode;
219     AttachSurface();
220 }
221 
SetAbilityBGAlpha(uint8_t alpha)222 void RSUIDirector::SetAbilityBGAlpha(uint8_t alpha)
223 {
224     auto node = surfaceNode_.lock();
225     if (!node) {
226         ROSEN_LOGI("RSUIDirector::SetAbilityBGAlpha, surfaceNode_ is nullptr");
227         return;
228     }
229     node->SetAbilityBGAlpha(alpha);
230 }
231 
SetRTRenderForced(bool isRenderForced)232 void RSUIDirector::SetRTRenderForced(bool isRenderForced)
233 {
234     RSRenderThread::Instance().SetRTRenderForced(isRenderForced);
235 }
236 
SetContainerWindow(bool hasContainerWindow,float density)237 void RSUIDirector::SetContainerWindow(bool hasContainerWindow, float density)
238 {
239     auto node = surfaceNode_.lock();
240     if (!node) {
241         ROSEN_LOGI("RSUIDirector::SetContainerWindow, surfaceNode_ is nullptr");
242         return;
243     }
244     node->SetContainerWindow(hasContainerWindow, density);
245 }
246 
SetRoot(NodeId root)247 void RSUIDirector::SetRoot(NodeId root)
248 {
249     if (root_ == root) {
250         ROSEN_LOGW("RSUIDirector::SetRoot, root_ is not change");
251         return;
252     }
253     root_ = root;
254     AttachSurface();
255 }
256 
AttachSurface()257 void RSUIDirector::AttachSurface()
258 {
259     auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_);
260     auto surfaceNode = surfaceNode_.lock();
261     if (node != nullptr && surfaceNode != nullptr) {
262         node->AttachRSSurfaceNode(surfaceNode);
263         ROSEN_LOGD("RSUIDirector::AttachSurface [%{public}" PRIu64, surfaceNode->GetId());
264     } else {
265         ROSEN_LOGD("RSUIDirector::AttachSurface not ready");
266     }
267 }
268 
SetAppFreeze(bool isAppFreeze)269 void RSUIDirector::SetAppFreeze(bool isAppFreeze)
270 {
271     auto surfaceNode = surfaceNode_.lock();
272     if (surfaceNode != nullptr) {
273         surfaceNode->SetFreeze(isAppFreeze);
274     }
275 }
276 
SetRequestVsyncCallback(const std::function<void ()> & callback)277 void RSUIDirector::SetRequestVsyncCallback(const std::function<void()>& callback)
278 {
279     std::unique_lock<std::mutex> lock(g_vsyncCallbackMutex);
280     requestVsyncCallback_ = callback;
281 }
282 
SetTimeStamp(uint64_t timeStamp,const std::string & abilityName)283 void RSUIDirector::SetTimeStamp(uint64_t timeStamp, const std::string& abilityName)
284 {
285     timeStamp_ = timeStamp;
286     abilityName_ = abilityName;
287 }
288 
SetCacheDir(const std::string & cacheFilePath)289 void RSUIDirector::SetCacheDir(const std::string& cacheFilePath)
290 {
291     cacheDir_ = cacheFilePath;
292 }
293 
FlushAnimation(uint64_t timeStamp,int64_t vsyncPeriod)294 bool RSUIDirector::FlushAnimation(uint64_t timeStamp, int64_t vsyncPeriod)
295 {
296     bool hasRunningAnimation = false;
297     auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
298     if (modifierManager != nullptr) {
299         modifierManager->SetDisplaySyncEnable(true);
300         modifierManager->SetFrameRateGetFunc([](const RSPropertyUnit unit, float velocity) -> int32_t {
301             return RSFrameRatePolicy::GetInstance()->GetExpectedFrameRate(unit, velocity);
302         });
303         hasRunningAnimation = modifierManager->Animate(timeStamp, vsyncPeriod);
304     }
305     return hasRunningAnimation;
306 }
307 
FlushAnimationStartTime(uint64_t timeStamp)308 void RSUIDirector::FlushAnimationStartTime(uint64_t timeStamp)
309 {
310     auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
311     if (modifierManager != nullptr) {
312         modifierManager->FlushStartAnimation(timeStamp);
313     }
314 }
315 
FlushModifier()316 void RSUIDirector::FlushModifier()
317 {
318     auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
319     if (modifierManager == nullptr) {
320         return;
321     }
322 
323     modifierManager->Draw();
324     // post animation finish callback(s) to task queue
325     RSUIDirector::RecvMessages();
326 }
327 
HasUIRunningAnimation()328 bool RSUIDirector::HasUIRunningAnimation()
329 {
330     auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
331     if (modifierManager != nullptr) {
332         return modifierManager->HasUIRunningAnimation();
333     }
334     return false;
335 }
336 
SetUITaskRunner(const TaskRunner & uiTaskRunner,int32_t instanceId)337 void RSUIDirector::SetUITaskRunner(const TaskRunner& uiTaskRunner, int32_t instanceId)
338 {
339     std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
340     instanceId_ = instanceId;
341     g_uiTaskRunners[this] = uiTaskRunner;
342     if (!isHgmConfigChangeCallbackReg_) {
343         RSFrameRatePolicy::GetInstance()->RegisterHgmConfigChangeCallback();
344         isHgmConfigChangeCallbackReg_ = true;
345     }
346 }
347 
SendMessages()348 void RSUIDirector::SendMessages()
349 {
350     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "SendCommands");
351     auto transactionProxy = RSTransactionProxy::GetInstance();
352     if (transactionProxy != nullptr) {
353         transactionProxy->FlushImplicitTransaction(timeStamp_, abilityName_);
354         index_ = transactionProxy->GetTransactionDataIndex();
355     } else {
356         RS_LOGE_LIMIT(__func__, __line__, "RSUIDirector::SendMessages failed, transactionProxy is nullptr");
357     }
358     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
359 }
360 
GetIndex() const361 uint32_t RSUIDirector::GetIndex() const
362 {
363     return index_;
364 }
365 
RecvMessages()366 void RSUIDirector::RecvMessages()
367 {
368     if (GetRealPid() == -1) {
369         return;
370     }
371     static const uint32_t pid = static_cast<uint32_t>(GetRealPid());
372     if (!RSMessageProcessor::Instance().HasTransaction(pid)) {
373         return;
374     }
375     auto transactionDataPtr = RSMessageProcessor::Instance().GetTransaction(pid);
376     RecvMessages(transactionDataPtr);
377 }
378 
RecvMessages(std::shared_ptr<RSTransactionData> cmds)379 void RSUIDirector::RecvMessages(std::shared_ptr<RSTransactionData> cmds)
380 {
381     if (cmds == nullptr || cmds->IsEmpty()) {
382         return;
383     }
384     ROSEN_LOGD("ProcessMessages begin");
385     RSUIDirector::ProcessMessages(cmds);
386 }
387 
ProcessMessages(std::shared_ptr<RSTransactionData> cmds)388 void RSUIDirector::ProcessMessages(std::shared_ptr<RSTransactionData> cmds)
389 {
390     // message ID for correspondence UI thread and IPC thread
391     static uint32_t messageId = 0;
392     std::map<int32_t, std::vector<std::unique_ptr<RSCommand>>> m;
393     for (auto &[id, _, cmd] : cmds->GetPayload()) {
394         NodeId realId = (id == 0 && cmd) ? cmd->GetNodeId() : id;
395         int32_t instanceId = RSNodeMap::Instance().GetNodeInstanceId(realId);
396         if (instanceId == INSTANCE_ID_UNDEFINED) {
397             instanceId = RSNodeMap::Instance().GetInstanceIdForReleasedNode(realId);
398         }
399         m[instanceId].push_back(std::move(cmd));
400     }
401     auto msgId = ++messageId;
402     RS_TRACE_NAME_FMT("RSUIDirector::ProcessMessages [messageId:%lu,cmdIndex:%llu,cmdCount:%lu]",
403         msgId, cmds->GetIndex(), cmds->GetCommandCount());
404     auto counter = std::make_shared<std::atomic_size_t>(m.size());
405     for (auto &[instanceId, commands] : m) {
406         ROSEN_LOGI("RSUIDirector::ProcessMessages messageId:%{public}d, cmdCount:%{public}lu, "
407             "instanceId:%{public}d", msgId, static_cast<unsigned long>(commands.size()), instanceId);
408         PostTask(
409             [cmds = std::make_shared<std::vector<std::unique_ptr<RSCommand>>>(std::move(commands)),
410                 counter, msgId, tempInstanceId = instanceId] {
411                 RS_TRACE_NAME_FMT("RSUIDirector::ProcessMessages PostTask messageId [%lu]", msgId);
412                 ROSEN_LOGI("RSUIDirector::PostTask messageId:%{public}d, cmdCount:%{public}lu, instanceId:%{public}d",
413                     msgId, static_cast<unsigned long>(cmds->size()), tempInstanceId);
414                 for (auto &cmd : *cmds) {
415                     RSContext context; // RSCommand->process() needs it
416                     cmd->Process(context);
417                 }
418                 if (counter->fetch_sub(1) == 1) {
419                     std::unique_lock<std::mutex> lock(g_vsyncCallbackMutex);
420                     if (requestVsyncCallback_ != nullptr) {
421                         requestVsyncCallback_();
422                     } else {
423                         RSTransaction::FlushImplicitTransaction();
424                     }
425                     ROSEN_LOGD("ProcessMessages end");
426                 }
427             }, instanceId);
428     }
429 }
430 
AnimationCallbackProcessor(NodeId nodeId,AnimationId animId,AnimationCallbackEvent event)431 void RSUIDirector::AnimationCallbackProcessor(NodeId nodeId, AnimationId animId, AnimationCallbackEvent event)
432 {
433     RSAnimationTraceUtils::GetInstance().addAnimationFinishTrace(
434         "Animation FinishCallback Processor", nodeId, animId, false);
435     // try find the node by nodeId
436     if (auto nodePtr = RSNodeMap::Instance().GetNode<RSNode>(nodeId)) {
437         if (!nodePtr->AnimationCallback(animId, event)) {
438             ROSEN_LOGE("RSUIDirector::AnimationCallbackProcessor, could not find animation %{public}" PRIu64 ""
439                 "on node %{public}" PRIu64, animId, nodeId);
440         }
441         return;
442     }
443 
444     // if node not found, try fallback node
445     auto& fallbackNode = RSNodeMap::Instance().GetAnimationFallbackNode();
446     if (fallbackNode && fallbackNode->AnimationCallback(animId, event)) {
447         ROSEN_LOGD("RSUIDirector::AnimationCallbackProcessor, found animation %{public}" PRIu64 " on fallback node.",
448             animId);
449     } else {
450         ROSEN_LOGE("RSUIDirector::AnimationCallbackProcessor, could not find animation %{public}" PRIu64 " on"
451             " fallback node.", animId);
452     }
453 }
454 
DumpNodeTreeProcessor(NodeId nodeId,pid_t pid,uint32_t taskId)455 void RSUIDirector::DumpNodeTreeProcessor(NodeId nodeId, pid_t pid, uint32_t taskId)
456 {
457     RS_TRACE_NAME_FMT("DumpClientNodeTree dump task[%u] node[%" PRIu64 "]", taskId, nodeId);
458     ROSEN_LOGI("DumpNodeTreeProcessor task[%{public}u] node[%" PRIu64 "]", taskId, nodeId);
459 
460     std::string out;
461     // use for dump transactionFlags [pid,index] in client tree dump
462     int32_t instanceId = RSNodeMap::Instance().GetNodeInstanceId(nodeId);
463     {
464         std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
465         for (const auto &[director, taskRunner] : g_uiTaskRunners) {
466             if (director->instanceId_ == instanceId) {
467                 out.append("transactionFlags:[ ").append(std::to_string(pid).append(", ")
468                     .append(std::to_string(director->index_)).append("]\r"));
469                 break;
470             }
471         }
472     }
473 
474     if (auto node = RSNodeMap::Instance().GetNode(nodeId)) {
475         constexpr int TOP_LEVEL_DEPTH = 1;
476         node->DumpTree(TOP_LEVEL_DEPTH, out);
477     }
478 
479     auto transactionProxy = RSTransactionProxy::GetInstance();
480     if (transactionProxy != nullptr) {
481         std::unique_ptr<RSCommand> command = std::make_unique<RSCommitDumpClientNodeTree>(
482             nodeId, getpid(), taskId, out);
483         transactionProxy->AddCommand(command, true);
484         RSTransaction::FlushImplicitTransaction();
485     }
486 }
487 
PostFrameRateTask(const std::function<void ()> & task)488 void RSUIDirector::PostFrameRateTask(const std::function<void()>& task)
489 {
490     PostTask(task);
491 }
492 
PostTask(const std::function<void ()> & task,int32_t instanceId)493 void RSUIDirector::PostTask(const std::function<void()>& task, int32_t instanceId)
494 {
495     PostDelayTask(task, 0, instanceId);
496 }
497 
PostDelayTask(const std::function<void ()> & task,uint32_t delay,int32_t instanceId)498 void RSUIDirector::PostDelayTask(const std::function<void()>& task, uint32_t delay, int32_t instanceId)
499 {
500     std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
501     for (const auto &[director, taskRunner] : g_uiTaskRunners) {
502         if (director->instanceId_ != instanceId) {
503             continue;
504         }
505         ROSEN_LOGD("RSUIDirector::PostTask instanceId=%{public}d success", instanceId);
506         taskRunner(task, delay);
507         return;
508     }
509     if (instanceId != INSTANCE_ID_UNDEFINED) {
510         ROSEN_LOGW("RSUIDirector::PostTask instanceId=%{public}d not found", instanceId);
511     }
512     for (const auto &[_, taskRunner] : g_uiTaskRunners) {
513         ROSEN_LOGD("RSUIDirector::PostTask success");
514         taskRunner(task, delay);
515         return;
516     }
517 }
518 
GetCurrentRefreshRateMode()519 int32_t RSUIDirector::GetCurrentRefreshRateMode()
520 {
521     return RSFrameRatePolicy::GetInstance()->GetRefreshRateModeName();
522 }
523 
GetAnimateExpectedRate() const524 int32_t RSUIDirector::GetAnimateExpectedRate() const
525 {
526     int32_t animateRate = 0;
527     auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
528     if (modifierManager != nullptr) {
529         auto& range = modifierManager->GetFrameRateRange();
530         if (range.IsValid()) {
531             animateRate = range.preferred_;
532         }
533     }
534     return animateRate;
535 }
536 } // namespace Rosen
537 } // namespace OHOS
538