1 /*
2 * Copyright (c) 2021-2023 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 "command/rs_message_processor.h"
22 #include "modifier/rs_modifier_manager.h"
23 #include "modifier/rs_modifier_manager_map.h"
24 #include "pipeline/rs_frame_report.h"
25 #include "pipeline/rs_node_map.h"
26 #include "pipeline/rs_render_thread.h"
27 #include "platform/common/rs_log.h"
28 #include "transaction/rs_application_agent_impl.h"
29 #include "transaction/rs_interfaces.h"
30 #include "transaction/rs_transaction_proxy.h"
31 #include "ui/rs_root_node.h"
32 #include "ui/rs_surface_extractor.h"
33 #include "ui/rs_surface_node.h"
34 #ifdef NEW_RENDER_CONTEXT
35 #include "render_context/memory_handler.h"
36 #endif
37
38 #ifdef _WIN32
39 #include <windows.h>
40 #define gettid GetCurrentThreadId
41 #endif
42
43 #ifdef __APPLE__
44 #define gettid getpid
45 #endif
46
47 #ifdef __gnu_linux__
48 #include <sys/types.h>
49 #include <sys/syscall.h>
50 #define gettid []() -> int32_t { return static_cast<int32_t>(syscall(SYS_gettid)); }
51 #endif
52
53 namespace OHOS {
54 namespace Rosen {
55 static std::unordered_map<RSUIDirector*, TaskRunner> g_uiTaskRunners;
56 static std::mutex g_uiTaskRunnersVisitorMutex;
57
Create()58 std::shared_ptr<RSUIDirector> RSUIDirector::Create()
59 {
60 return std::shared_ptr<RSUIDirector>(new RSUIDirector());
61 }
62
~RSUIDirector()63 RSUIDirector::~RSUIDirector()
64 {
65 Destroy();
66 }
67
Init(bool shouldCreateRenderThread)68 void RSUIDirector::Init(bool shouldCreateRenderThread)
69 {
70 AnimationCommandHelper::SetAnimationCallbackProcessor(AnimationCallbackProcessor);
71
72 isUniRenderEnabled_ = RSSystemProperties::GetUniRenderEnabled();
73 if (shouldCreateRenderThread && !isUniRenderEnabled_) {
74 auto renderThreadClient = RSIRenderClient::CreateRenderThreadClient();
75 auto transactionProxy = RSTransactionProxy::GetInstance();
76 if (transactionProxy != nullptr) {
77 transactionProxy->SetRenderThreadClient(renderThreadClient);
78 }
79
80 RsFrameReport::GetInstance().Init();
81 if (!cacheDir_.empty()) {
82 RSRenderThread::Instance().SetCacheDir(cacheDir_);
83 }
84 RSRenderThread::Instance().Start();
85 }
86 RSApplicationAgentImpl::Instance().RegisterRSApplicationAgent();
87
88 GoForeground();
89 }
90
GoForeground()91 void RSUIDirector::GoForeground()
92 {
93 ROSEN_LOGD("RSUIDirector::GoForeground");
94 if (!isActive_) {
95 if (!isUniRenderEnabled_) {
96 RSRenderThread::Instance().UpdateWindowStatus(true);
97 }
98 isActive_ = true;
99 if (auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_)) {
100 node->SetEnableRender(true);
101 }
102 auto surfaceNode = surfaceNode_.lock();
103 if (surfaceNode) {
104 surfaceNode->MarkUIHidden(false);
105 }
106 }
107 }
108
GoBackground()109 void RSUIDirector::GoBackground()
110 {
111 ROSEN_LOGD("RSUIDirector::GoBackground");
112 if (isActive_) {
113 if (!isUniRenderEnabled_) {
114 RSRenderThread::Instance().UpdateWindowStatus(false);
115 }
116 isActive_ = false;
117 if (auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_)) {
118 node->SetEnableRender(false);
119 }
120 auto surfaceNode = surfaceNode_.lock();
121 if (surfaceNode) {
122 surfaceNode->MarkUIHidden(true);
123 }
124 // clean bufferQueue cache
125 RSRenderThread::Instance().PostTask([surfaceNode]() {
126 if (surfaceNode != nullptr) {
127 #ifdef NEW_RENDER_CONTEXT
128 std::shared_ptr<RSRenderSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
129 #else
130 std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
131 #endif
132 rsSurface->ClearBuffer();
133 }
134 });
135 #ifdef ACE_ENABLE_GL
136 RSRenderThread::Instance().PostTask([this]() {
137 auto renderContext = RSRenderThread::Instance().GetRenderContext();
138 if (renderContext != nullptr) {
139 #ifndef ROSEN_CROSS_PLATFORM
140 #if defined(NEW_RENDER_CONTEXT)
141 auto drawingContext = RSRenderThread::Instance().GetDrawingContext();
142 MemoryHandler::ClearRedundantResources(drawingContext->GetDrawingContext());
143 #else
144 renderContext->ClearRedundantResources();
145 #endif
146 #endif
147 }
148 });
149 #endif
150 }
151 }
152
Destroy()153 void RSUIDirector::Destroy()
154 {
155 if (root_ != 0) {
156 if (!isUniRenderEnabled_) {
157 if (auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_)) {
158 node->RemoveFromTree();
159 }
160 }
161 root_ = 0;
162 }
163 GoBackground();
164 std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
165 g_uiTaskRunners.erase(this);
166 }
167
SetRSSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode)168 void RSUIDirector::SetRSSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode)
169 {
170 surfaceNode_ = surfaceNode;
171 AttachSurface();
172 }
173
SetAbilityBGAlpha(uint8_t alpha)174 void RSUIDirector::SetAbilityBGAlpha(uint8_t alpha)
175 {
176 auto node = surfaceNode_.lock();
177 if (!node) {
178 ROSEN_LOGI("RSUIDirector::SetAbilityBGAlpha, surfaceNode_ is nullptr");
179 return;
180 }
181 node->SetAbilityBGAlpha(alpha);
182 }
183
SetRTRenderForced(bool isRenderForced)184 void RSUIDirector::SetRTRenderForced(bool isRenderForced)
185 {
186 RSRenderThread::Instance().SetRTRenderForced(isRenderForced);
187 }
188
SetContainerWindow(bool hasContainerWindow,float density)189 void RSUIDirector::SetContainerWindow(bool hasContainerWindow, float density)
190 {
191 auto node = surfaceNode_.lock();
192 if (!node) {
193 ROSEN_LOGI("RSUIDirector::SetContainerWindow, surfaceNode_ is nullptr");
194 return;
195 }
196 node->SetContainerWindow(hasContainerWindow, density);
197 }
198
SetRoot(NodeId root)199 void RSUIDirector::SetRoot(NodeId root)
200 {
201 if (root_ == root) {
202 ROSEN_LOGW("RSUIDirector::SetRoot, root_ is not change");
203 return;
204 }
205 root_ = root;
206 AttachSurface();
207 }
208
AttachSurface()209 void RSUIDirector::AttachSurface()
210 {
211 auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_);
212 auto surfaceNode = surfaceNode_.lock();
213 if (node != nullptr && surfaceNode != nullptr) {
214 node->AttachRSSurfaceNode(surfaceNode);
215 ROSEN_LOGD("RSUIDirector::AttachSurface [%" PRIu64 "]", surfaceNode->GetId());
216 } else {
217 ROSEN_LOGD("RSUIDirector::AttachSurface not ready");
218 }
219 }
220
SetAppFreeze(bool isAppFreeze)221 void RSUIDirector::SetAppFreeze(bool isAppFreeze)
222 {
223 auto surfaceNode = surfaceNode_.lock();
224 if (surfaceNode != nullptr) {
225 surfaceNode->SetFreeze(isAppFreeze);
226 }
227 }
228
SetTimeStamp(uint64_t timeStamp,const std::string & abilityName)229 void RSUIDirector::SetTimeStamp(uint64_t timeStamp, const std::string& abilityName)
230 {
231 timeStamp_ = timeStamp;
232 abilityName_ = abilityName;
233 }
234
SetCacheDir(const std::string & cacheFilePath)235 void RSUIDirector::SetCacheDir(const std::string& cacheFilePath)
236 {
237 cacheDir_ = cacheFilePath;
238 }
239
RunningCustomAnimation(uint64_t timeStamp)240 bool RSUIDirector::RunningCustomAnimation(uint64_t timeStamp)
241 {
242 bool hasRunningAnimation = false;
243 auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
244 if (modifierManager == nullptr) {
245 return hasRunningAnimation;
246 }
247
248 hasRunningAnimation = modifierManager->Animate(timeStamp);
249 modifierManager->Draw();
250
251 // post animation finish callback(s) to task queue
252 RSUIDirector::RecvMessages();
253 return hasRunningAnimation;
254 }
255
SetUITaskRunner(const TaskRunner & uiTaskRunner)256 void RSUIDirector::SetUITaskRunner(const TaskRunner& uiTaskRunner)
257 {
258 std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
259 g_uiTaskRunners[this] = uiTaskRunner;
260 }
261
SendMessages()262 void RSUIDirector::SendMessages()
263 {
264 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "SendCommands");
265 auto transactionProxy = RSTransactionProxy::GetInstance();
266 if (transactionProxy != nullptr) {
267 transactionProxy->FlushImplicitTransaction(timeStamp_, abilityName_);
268 }
269 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
270 }
271
RecvMessages()272 void RSUIDirector::RecvMessages()
273 {
274 if (GetRealPid() == -1) {
275 return;
276 }
277 static const uint32_t pid = static_cast<uint32_t>(GetRealPid());
278 static std::mutex recvMessagesMutex;
279 std::unique_lock<std::mutex> lock(recvMessagesMutex);
280 if (RSMessageProcessor::Instance().HasTransaction(pid)) {
281 auto transactionDataPtr = RSMessageProcessor::Instance().GetTransaction(pid);
282 RecvMessages(transactionDataPtr);
283 }
284 }
285
RecvMessages(std::shared_ptr<RSTransactionData> cmds)286 void RSUIDirector::RecvMessages(std::shared_ptr<RSTransactionData> cmds)
287 {
288 if (cmds == nullptr || cmds->IsEmpty()) {
289 return;
290 }
291 ROSEN_LOGD("RSUIDirector::RecvMessages success");
292 PostTask([cmds]() {
293 ROSEN_LOGD("RSUIDirector::ProcessMessages success");
294 RSUIDirector::ProcessMessages(cmds);
295 });
296 }
297
ProcessMessages(std::shared_ptr<RSTransactionData> cmds)298 void RSUIDirector::ProcessMessages(std::shared_ptr<RSTransactionData> cmds)
299 {
300 static RSContext context; // RSCommand->process() needs it
301 cmds->Process(context);
302 }
303
AnimationCallbackProcessor(NodeId nodeId,AnimationId animId,AnimationCallbackEvent event)304 void RSUIDirector::AnimationCallbackProcessor(NodeId nodeId, AnimationId animId, AnimationCallbackEvent event)
305 {
306 // try find the node by nodeId
307 if (auto nodePtr = RSNodeMap::Instance().GetNode<RSNode>(nodeId)) {
308 if (!nodePtr->AnimationCallback(animId, event)) {
309 ROSEN_LOGE("RSUIDirector::AnimationCallbackProcessor, could not find animation %" PRIu64 " on node %" PRIu64
310 ".", animId, nodeId);
311 }
312 return;
313 }
314
315 // if node not found, try fallback node
316 auto& fallbackNode = RSNodeMap::Instance().GetAnimationFallbackNode();
317 if (fallbackNode && fallbackNode->AnimationCallback(animId, event)) {
318 ROSEN_LOGD("RSUIDirector::AnimationCallbackProcessor, found animation %" PRIu64 " on fallback node.", animId);
319 } else {
320 ROSEN_LOGE("RSUIDirector::AnimationCallbackProcessor, could not find animation %" PRIu64 " on fallback node.",
321 animId);
322 }
323 }
324
PostTask(const std::function<void ()> & task)325 void RSUIDirector::PostTask(const std::function<void()>& task)
326 {
327 std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
328 for (auto [_, taskRunner] : g_uiTaskRunners) {
329 if (taskRunner == nullptr) {
330 ROSEN_LOGE("RSUIDirector::PostTask, uiTaskRunner is null");
331 continue;
332 }
333 ROSEN_LOGD("RSUIDirector::PostTask success");
334 taskRunner(task);
335 return;
336 }
337 }
338 } // namespace Rosen
339 } // namespace OHOS
340