• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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_base_node.h"
17 
18 #include <algorithm>
19 #include <sstream>
20 
21 #include "sandbox_utils.h"
22 
23 #include "command/rs_base_node_command.h"
24 #include "pipeline/rs_node_map.h"
25 #include "platform/common/rs_log.h"
26 #include "transaction/rs_transaction_proxy.h"
27 #include "ui/rs_canvas_node.h"
28 #include "ui/rs_display_node.h"
29 #include "ui/rs_proxy_node.h"
30 #include "ui/rs_root_node.h"
31 #include "ui/rs_surface_node.h"
32 
33 namespace OHOS {
34 namespace Rosen {
35 namespace {
36 static bool gIsUniRenderEnabled = false;
37 }
38 
GenerateId()39 NodeId RSBaseNode::GenerateId()
40 {
41     static pid_t pid_ = GetRealPid();
42     static std::atomic<uint32_t> currentId_ = 0;
43 
44     auto currentId = currentId_.fetch_add(1, std::memory_order_relaxed);
45     if (currentId == UINT32_MAX) {
46         // [PLANNING]:process the overflow situations
47         ROSEN_LOGE("Node Id overflow");
48     }
49 
50     // concat two 32-bit numbers to one 64-bit number
51     return ((NodeId)pid_ << 32) | currentId;
52 }
53 
InitUniRenderEnabled()54 void RSBaseNode::InitUniRenderEnabled()
55 {
56     static bool inited = false;
57     if (!inited) {
58         inited = true;
59         gIsUniRenderEnabled = RSSystemProperties::GetUniRenderEnabled();
60         ROSEN_LOGD("RSBaseNode::InitUniRenderEnabled:%d", gIsUniRenderEnabled);
61     }
62 }
63 
RSBaseNode(bool isRenderServiceNode)64 RSBaseNode::RSBaseNode(bool isRenderServiceNode) : RSBaseNode(isRenderServiceNode, GenerateId()) {}
65 
RSBaseNode(bool isRenderServiceNode,NodeId id)66 RSBaseNode::RSBaseNode(bool isRenderServiceNode, NodeId id) : isRenderServiceNode_(isRenderServiceNode), id_(id)
67 {
68     InitUniRenderEnabled();
69 }
70 
~RSBaseNode()71 RSBaseNode::~RSBaseNode()
72 {
73     // break current (ui) parent-child relationship.
74     // render nodes will check if its child is expired and remove it, no need to manually remove it here.
75     if (auto parentPtr = RSNodeMap::Instance().GetNode(parent_)) {
76         parentPtr->RemoveChildById(id_);
77     }
78     // unregister node from node map
79     RSNodeMap::MutableInstance().UnregisterNode(id_);
80 
81     // tell RT/RS to destroy related render node
82     auto transactionProxy = RSTransactionProxy::GetInstance();
83     if (transactionProxy == nullptr || skipDestroyCommandInDestructor_) {
84         return;
85     }
86     std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeDestroy>(id_);
87     transactionProxy->AddCommand(command, IsRenderServiceNode());
88     if (NeedSendExtraCommand()) {
89         std::unique_ptr<RSCommand> extraCommand = std::make_unique<RSBaseNodeDestroy>(id_);
90         transactionProxy->AddCommand(extraCommand, !IsRenderServiceNode());
91     }
92 }
93 
IsUniRenderEnabled() const94 bool RSBaseNode::IsUniRenderEnabled() const
95 {
96     return gIsUniRenderEnabled;
97 }
98 
IsRenderServiceNode() const99 bool RSBaseNode::IsRenderServiceNode() const
100 {
101     return gIsUniRenderEnabled || isRenderServiceNode_;
102 }
103 
NeedSendExtraCommand() const104 bool RSBaseNode::NeedSendExtraCommand() const
105 {
106     return gIsUniRenderEnabled && !isRenderServiceNode_;
107 }
108 
AddChild(SharedPtr child,int index)109 void RSBaseNode::AddChild(SharedPtr child, int index)
110 {
111     if (child == nullptr) {
112         ROSEN_LOGE("RSBaseNode::AddChild, child is nullptr");
113         return;
114     }
115     if (child->parent_ == id_) {
116         ROSEN_LOGI("RSBaseNode::AddChild, child already exist");
117         return;
118     }
119     NodeId childId = child->GetId();
120     if (child->parent_ != 0) {
121         child->RemoveFromTree();
122     }
123 
124     if (index < 0 || index >= static_cast<int>(children_.size())) {
125         children_.push_back(childId);
126     } else {
127         children_.insert(children_.begin() + index, childId);
128     }
129     child->SetParent(id_);
130     child->OnAddChildren();
131     auto transactionProxy = RSTransactionProxy::GetInstance();
132     if (transactionProxy == nullptr) {
133         return;
134     }
135     // construct command using child's GetHierarchyCommandNodeId(), not GetId()
136     childId = child->GetHierarchyCommandNodeId();
137     std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeAddChild>(id_, childId, index);
138     bool disallowSendToRemote = gIsUniRenderEnabled && !RSSystemProperties::IsUniRenderMode() && // dynamic-Non Uni
139         !isRenderServiceNode_ && !IsInstanceOf(RSUINodeType::SURFACE_NODE) && // canvas/root node
140         child->IsInstanceOf(RSUINodeType::SURFACE_NODE);
141     if (disallowSendToRemote) {
142         transactionProxy->AddCommand(command, false, GetFollowType(), id_);
143         return;
144     }
145     transactionProxy->AddCommand(command, IsRenderServiceNode(), GetFollowType(), id_);
146     if (NeedSendExtraCommand()) {
147         std::unique_ptr<RSCommand> extraCommand = std::make_unique<RSBaseNodeAddChild>(id_, childId, index);
148         transactionProxy->AddCommand(extraCommand, !IsRenderServiceNode(), GetFollowType(), id_);
149     }
150 }
151 
MoveChild(SharedPtr child,int index)152 void RSBaseNode::MoveChild(SharedPtr child, int index)
153 {
154     if (child == nullptr || child->parent_ != id_) {
155         ROSEN_LOGD("RSBaseNode::MoveChild, not valid child");
156         return;
157     }
158     NodeId childId = child->GetId();
159     auto itr = std::find(children_.begin(), children_.end(), childId);
160     if (itr == children_.end()) {
161         ROSEN_LOGD("RSBaseNode::MoveChild, not child");
162         return;
163     }
164     children_.erase(itr);
165     if (index < 0 || index >= static_cast<int>(children_.size())) {
166         children_.push_back(childId);
167     } else {
168         children_.insert(children_.begin() + index, childId);
169     }
170 
171     auto transactionProxy = RSTransactionProxy::GetInstance();
172     if (transactionProxy == nullptr) {
173         return;
174     }
175     // construct command using child's GetHierarchyCommandNodeId(), not GetId()
176     childId = child->GetHierarchyCommandNodeId();
177     std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeMoveChild>(id_, childId, index);
178     bool disallowSendToRemote = gIsUniRenderEnabled && !RSSystemProperties::IsUniRenderMode() && // dynamic-Non Uni
179                                 !isRenderServiceNode_ &&
180                                 !IsInstanceOf(RSUINodeType::SURFACE_NODE) && // canvas/root node
181                                 child->IsInstanceOf(RSUINodeType::SURFACE_NODE);
182     if (disallowSendToRemote) {
183         transactionProxy->AddCommand(command, false, GetFollowType(), id_);
184         return;
185     }
186     transactionProxy->AddCommand(command, IsRenderServiceNode(), GetFollowType(), id_);
187     if (NeedSendExtraCommand()) {
188         std::unique_ptr<RSCommand> extraCommand = std::make_unique<RSBaseNodeMoveChild>(id_, childId, index);
189         transactionProxy->AddCommand(extraCommand, !IsRenderServiceNode(), GetFollowType(), id_);
190     }
191 }
192 
RemoveChild(SharedPtr child)193 void RSBaseNode::RemoveChild(SharedPtr child)
194 {
195     if (child == nullptr || child->parent_ != id_) {
196         ROSEN_LOGI("RSBaseNode::RemoveChild, child is nullptr");
197         return;
198     }
199     NodeId childId = child->GetId();
200     RemoveChildById(childId);
201     child->OnRemoveChildren();
202     child->SetParent(0);
203 
204     auto transactionProxy = RSTransactionProxy::GetInstance();
205     if (transactionProxy == nullptr) {
206         return;
207     }
208     // construct command using child's GetHierarchyCommandNodeId(), not GetId()
209     childId = child->GetHierarchyCommandNodeId();
210     std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeRemoveChild>(id_, childId);
211     transactionProxy->AddCommand(command, IsRenderServiceNode(), GetFollowType(), id_);
212     if (NeedSendExtraCommand()) {
213         std::unique_ptr<RSCommand> extraCommand = std::make_unique<RSBaseNodeRemoveChild>(id_, childId);
214         transactionProxy->AddCommand(extraCommand, !IsRenderServiceNode(), GetFollowType(), id_);
215     }
216 }
217 
AddCrossParentChild(SharedPtr child,int index)218 void RSBaseNode::AddCrossParentChild(SharedPtr child, int index)
219 {
220     // AddCrossParentChild only used as: the child is under multiple parents(e.g. a window cross multi-screens),
221     // so this child will not remove from the old parent.
222     if (child == nullptr) {
223         ROSEN_LOGE("RSBaseNode::AddCrossScreenChild, child is nullptr");
224         return;
225     }
226     if (!this->IsInstanceOf<RSDisplayNode>()) {
227         ROSEN_LOGE("RSBaseNode::AddCrossScreenChild, only displayNode support AddCrossScreenChild");
228         return;
229     }
230     NodeId childId = child->GetId();
231 
232     if (index < 0 || index >= static_cast<int>(children_.size())) {
233         children_.push_back(childId);
234     } else {
235         children_.insert(children_.begin() + index, childId);
236     }
237     child->SetParent(id_);
238     child->OnAddChildren();
239     auto transactionProxy = RSTransactionProxy::GetInstance();
240     if (transactionProxy == nullptr) {
241         return;
242     }
243     // construct command using child's GetHierarchyCommandNodeId(), not GetId()
244     childId = child->GetHierarchyCommandNodeId();
245     std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeAddCrossParentChild>(id_, childId, index);
246     bool disallowSendToRemote = gIsUniRenderEnabled && !RSSystemProperties::IsUniRenderMode() && // dynamic-Non Uni
247                                 !isRenderServiceNode_ &&
248                                 !IsInstanceOf(RSUINodeType::SURFACE_NODE) && // canvas/root node
249                                 child->IsInstanceOf(RSUINodeType::SURFACE_NODE);
250     if (disallowSendToRemote) {
251         transactionProxy->AddCommand(command, false, GetFollowType(), id_);
252         return;
253     }
254     transactionProxy->AddCommand(command, IsRenderServiceNode(), GetFollowType(), id_);
255     if (NeedSendExtraCommand()) {
256         std::unique_ptr<RSCommand> extraCommand = std::make_unique<RSBaseNodeAddCrossParentChild>(id_, childId, index);
257         transactionProxy->AddCommand(extraCommand, !IsRenderServiceNode(), GetFollowType(), id_);
258     }
259 }
260 
RemoveCrossParentChild(SharedPtr child,NodeId newParentId)261 void RSBaseNode::RemoveCrossParentChild(SharedPtr child, NodeId newParentId)
262 {
263     // RemoveCrossParentChild only used as: the child is under multiple parents(e.g. a window cross multi-screens),
264     // set the newParentId to rebuild the parent-child relationship.
265     if (child == nullptr) {
266         ROSEN_LOGI("RSBaseNode::RemoveCrossScreenChild, child is nullptr");
267         return;
268     }
269     if (!this->IsInstanceOf<RSDisplayNode>()) {
270         ROSEN_LOGE("RSBaseNode::RemoveCrossScreenChild, only displayNode support RemoveCrossScreenChild");
271         return;
272     }
273     NodeId childId = child->GetId();
274     RemoveChildById(childId);
275     child->OnRemoveChildren();
276     child->SetParent(newParentId);
277 
278     auto transactionProxy = RSTransactionProxy::GetInstance();
279     if (transactionProxy == nullptr) {
280         return;
281     }
282     // construct command using child's GetHierarchyCommandNodeId(), not GetId()
283     childId = child->GetHierarchyCommandNodeId();
284     std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeRemoveCrossParentChild>(id_, childId, newParentId);
285     transactionProxy->AddCommand(command, IsRenderServiceNode(), GetFollowType(), id_);
286     if (NeedSendExtraCommand()) {
287         std::unique_ptr<RSCommand> extraCommand =
288             std::make_unique<RSBaseNodeRemoveCrossParentChild>(id_, childId, newParentId);
289         transactionProxy->AddCommand(extraCommand, !IsRenderServiceNode(), GetFollowType(), id_);
290     }
291 }
292 
RemoveChildById(NodeId childId)293 void RSBaseNode::RemoveChildById(NodeId childId)
294 {
295     auto itr = std::find(children_.begin(), children_.end(), childId);
296     if (itr != children_.end()) {
297         children_.erase(itr);
298     }
299 }
300 
RemoveFromTree()301 void RSBaseNode::RemoveFromTree()
302 {
303     if (auto parentPtr = RSNodeMap::Instance().GetNode(parent_)) {
304         parentPtr->RemoveChildById(GetId());
305         OnRemoveChildren();
306         SetParent(0);
307     }
308     // always send Remove-From-Tree command
309     auto transactionProxy = RSTransactionProxy::GetInstance();
310     if (transactionProxy == nullptr) {
311         return;
312     }
313     // construct command using own GetHierarchyCommandNodeId(), not GetId()
314     auto nodeId = GetHierarchyCommandNodeId();
315     std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeRemoveFromTree>(nodeId);
316     transactionProxy->AddCommand(command, IsRenderServiceNode(), GetFollowType(), nodeId);
317     if (NeedSendExtraCommand()) {
318         std::unique_ptr<RSCommand> extraCommand = std::make_unique<RSBaseNodeRemoveFromTree>(nodeId);
319         transactionProxy->AddCommand(extraCommand, !IsRenderServiceNode(), GetFollowType(), nodeId);
320     }
321 }
322 
ClearChildren()323 void RSBaseNode::ClearChildren()
324 {
325     for (auto child : children_) {
326         if (auto childPtr = RSNodeMap::Instance().GetNode(child)) {
327             childPtr->SetParent(0);
328         }
329     }
330     children_.clear();
331 
332     auto transactionProxy = RSTransactionProxy::GetInstance();
333     if (transactionProxy == nullptr) {
334         return;
335     }
336     // construct command using own GetHierarchyCommandNodeId(), not GetId()
337     auto nodeId = GetHierarchyCommandNodeId();
338     std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeClearChild>(nodeId);
339     transactionProxy->AddCommand(command, IsRenderServiceNode(), GetFollowType(), nodeId);
340     if (NeedSendExtraCommand()) {
341         std::unique_ptr<RSCommand> extraCommand = std::make_unique<RSBaseNodeClearChild>(nodeId);
342         transactionProxy->AddCommand(extraCommand, !IsRenderServiceNode(), GetFollowType(), nodeId);
343     }
344 }
345 
SetParent(NodeId parentId)346 void RSBaseNode::SetParent(NodeId parentId)
347 {
348     parent_ = parentId;
349 }
350 
GetParent()351 RSBaseNode::SharedPtr RSBaseNode::GetParent()
352 {
353     return RSNodeMap::Instance().GetNode(parent_);
354 }
355 
DumpNode(int depth) const356 std::string RSBaseNode::DumpNode(int depth) const
357 {
358     std::stringstream ss;
359     auto it = RSUINodeTypeStrs.find(GetType());
360     if (it == RSUINodeTypeStrs.end()) {
361         return "";
362     }
363     ss << it->second << "[" << std::to_string(id_) << "] child[";
364     for (auto child : children_) {
365         ss << std::to_string(child) << " ";
366     }
367     ss << "]";
368     return ss.str();
369 }
370 
IsInstanceOf(RSUINodeType type) const371 bool RSBaseNode::IsInstanceOf(RSUINodeType type) const
372 {
373     auto targetType = static_cast<uint32_t>(type);
374     auto instanceType = static_cast<uint32_t>(GetType());
375     // use bitmask to check whether the instance is a subclass of the target type
376     return (instanceType & targetType) == targetType;
377 }
378 
379 template<typename T>
IsInstanceOf() const380 bool RSBaseNode::IsInstanceOf() const
381 {
382     return IsInstanceOf(T::Type);
383 }
384 
385 // explicit instantiation with all render node types
386 template bool RSBaseNode::IsInstanceOf<RSBaseNode>() const;
387 template bool RSBaseNode::IsInstanceOf<RSDisplayNode>() const;
388 template bool RSBaseNode::IsInstanceOf<RSNode>() const;
389 template bool RSBaseNode::IsInstanceOf<RSSurfaceNode>() const;
390 template bool RSBaseNode::IsInstanceOf<RSProxyNode>() const;
391 template bool RSBaseNode::IsInstanceOf<RSCanvasNode>() const;
392 template bool RSBaseNode::IsInstanceOf<RSRootNode>() const;
393 
394 } // namespace Rosen
395 } // namespace OHOS
396