• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "core/components_ng/base/distributed_ui.h"
17 
18 #include <chrono>
19 #include <unordered_map>
20 
21 #include "base/ressched/ressched_report.h"
22 #include "core/components_ng/pattern/common_view/common_view_pattern.h"
23 #include "core/components_ng/pattern/custom/custom_node.h"
24 #include "core/components_ng/pattern/divider/divider_pattern.h"
25 #include "core/components_ng/pattern/flex/flex_layout_pattern.h"
26 #include "core/components_ng/pattern/image/image_pattern.h"
27 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
28 #include "core/components_ng/pattern/linear_layout/linear_layout_property.h"
29 #include "core/components_ng/pattern/list/list_item_pattern.h"
30 #include "core/components_ng/pattern/list/list_pattern.h"
31 #include "core/components_ng/pattern/stack/stack_pattern.h"
32 #include "core/components_ng/pattern/stage/page_pattern.h"
33 #include "core/components_ng/pattern/swiper/swiper_pattern.h"
34 #include "core/components_ng/pattern/tabs/tab_bar_pattern.h"
35 #include "core/components_ng/pattern/tabs/tab_content_node.h"
36 #include "core/components_ng/pattern/tabs/tab_content_pattern.h"
37 #include "core/components_ng/pattern/tabs/tabs_model_ng.h"
38 #include "core/components_ng/pattern/tabs/tabs_pattern.h"
39 #include "core/components_ng/pattern/text/text_model_ng.h"
40 #include "core/components_ng/pattern/text/text_pattern.h"
41 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
42 #include "core/components_ng/syntax/for_each_node.h"
43 #include "core/components_ng/syntax/if_else_node.h"
44 #include "core/components_ng/syntax/lazy_for_each_node.h"
45 #include "core/components_ng/syntax/syntax_item.h"
46 #include "core/components_v2/inspector/inspector_constants.h"
47 #include "core/pipeline/base/element_register.h"
48 #include "core/pipeline_ng/pipeline_context.h"
49 
50 namespace OHOS::Ace::NG {
51 namespace {
52 const char DISTRIBUTE_UI_TYPE[] = "$type";
53 const char DISTRIBUTE_UI_ID[] = "$ID";
54 const char DISTRIBUTE_UI_ATTRS[] = "$attrs";
55 const char DISTRIBUTE_UI_PARENT[] = "$parent";
56 const char DISTRIBUTE_UI_DEPTH[] = "$depth";
57 const char DISTRIBUTE_UI_OPERATION[] = "$op";
58 
59 const int32_t HANDLE_UPDATE_PER_VSYNC = 1;
60 
RestorePageNode(const RefPtr<NG::FrameNode> & pageNode)61 void RestorePageNode(const RefPtr<NG::FrameNode>& pageNode)
62 {
63     auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
64     CHECK_NULL_VOID(pagePattern);
65     pagePattern->SetOnBackPressed([]() { return true; });
66 }
67 } // namespace
68 
DumpUITree()69 SerializeableObjectArray DistributedUI::DumpUITree()
70 {
71     ResetDirtyNodes();
72 
73     auto context = NG::PipelineContext::GetCurrentContext();
74     CHECK_NULL_RETURN(context, SerializeableObjectArray());
75     auto pageRootNode = currentPageId_ ? context->GetStageManager()->GetPageById(currentPageId_)
76                                        : context->GetStageManager()->GetLastPage();
77     CHECK_NULL_RETURN(pageRootNode, SerializeableObjectArray());
78 
79     SerializeableObjectArray objectArray;
80     auto children = pageRootNode->GetChildren();
81     for (const auto& uiNode : children) {
82         DumpTreeInner(uiNode, objectArray, 1);
83     }
84 
85     status_ = StateMachine::SOURCE_START;
86 
87     return objectArray;
88 }
89 
SubscribeUpdate(const std::function<void (int32_t,SerializeableObjectArray &)> & onUpdate)90 void DistributedUI::SubscribeUpdate(const std::function<void(int32_t, SerializeableObjectArray&)>& onUpdate)
91 {
92     onUpdateCb_ = std::move(onUpdate);
93 }
94 
UnSubscribeUpdate()95 void DistributedUI::UnSubscribeUpdate()
96 {
97     onUpdateCb_ = nullptr;
98     status_ = StateMachine::STOP;
99 }
100 
ProcessSerializeableInputEvent(const SerializeableObjectArray & array)101 void DistributedUI::ProcessSerializeableInputEvent(const SerializeableObjectArray& array)
102 {
103     auto context = NG::PipelineContext::GetCurrentContext();
104     CHECK_NULL_VOID(context);
105 
106     TouchEvent event;
107     std::unique_ptr<JsonValue>& json = (std::unique_ptr<JsonValue>&)array.front();
108     event.FromJson(json);
109     bool isSubPipe = json->GetBool("sub");
110 
111     context->OnTouchEvent(event, isSubPipe);
112 }
113 
RestoreUITree(const SerializeableObjectArray & array)114 void DistributedUI::RestoreUITree(const SerializeableObjectArray& array)
115 {
116     status_ = StateMachine::SINK_START;
117     RestoreUITreeInner(array);
118 }
119 
UpdateUITree(const SerializeableObjectArray & array)120 void DistributedUI::UpdateUITree(const SerializeableObjectArray& array)
121 {
122     if (status_ != StateMachine::SINK_START) {
123         return;
124     }
125     pendingUpdates_.emplace_back(std::move((SerializeableObjectArray&)array));
126 
127     auto context = NG::PipelineContext::GetCurrentContext();
128     CHECK_NULL_VOID(context);
129     context->RequestFrame();
130 }
131 
SubscribeInputEventProcess(const std::function<void (SerializeableObjectArray &)> & onEvent)132 void DistributedUI::SubscribeInputEventProcess(const std::function<void(SerializeableObjectArray&)>& onEvent)
133 {
134     onEventCb_ = std::move(onEvent);
135 }
136 
UnSubscribeInputEventProcess()137 void DistributedUI::UnSubscribeInputEventProcess()
138 {
139     onEventCb_ = nullptr;
140     status_ = StateMachine::STOP;
141     pendingUpdates_.clear();
142 }
143 
AddDeletedNode(int32_t nodeId)144 void DistributedUI::AddDeletedNode(int32_t nodeId)
145 {
146     if (!ReadyToDumpUpdate()) {
147         return;
148     }
149     deletedNodes_.emplace(nodeId);
150 }
151 
AddNewNode(int32_t nodeId)152 void DistributedUI::AddNewNode(int32_t nodeId)
153 {
154     if (!ReadyToDumpUpdate()) {
155         return;
156     }
157     newNodes_.emplace(nodeId);
158 }
159 
AddDirtyCustomNode(int32_t nodeId)160 void DistributedUI::AddDirtyCustomNode(int32_t nodeId)
161 {
162     if (!ReadyToDumpUpdate()) {
163         return;
164     }
165     dirtyCustomNodes_.emplace(nodeId);
166 }
167 
AddDirtyRenderNode(int32_t nodeId)168 void DistributedUI::AddDirtyRenderNode(int32_t nodeId)
169 {
170     if (!ReadyToDumpUpdate()) {
171         return;
172     }
173     dirtyRenderNodes_.emplace(nodeId);
174 }
175 
AddDirtyLayoutNode(int32_t nodeId)176 void DistributedUI::AddDirtyLayoutNode(int32_t nodeId)
177 {
178     if (!ReadyToDumpUpdate()) {
179         return;
180     }
181     dirtyLayoutNodes_.emplace(nodeId);
182 }
183 
OnTreeUpdate()184 void DistributedUI::OnTreeUpdate()
185 {
186     if (!ReadyToDumpUpdate()) {
187         return;
188     }
189 
190 #ifdef ACE_DEBUG_LOG
191     auto timeStart = std::chrono::high_resolution_clock::now();
192 #endif
193 
194     DistributedUI::UpdateType updateType;
195     SerializeableObjectArray update;
196     if (pageChangeFlag_) {
197         pageChangeFlag_ = false;
198         ResetDirtyNodes();
199         update = DumpUITree();
200         updateType = UpdateType::PAGE_CHANGE;
201     } else {
202         update = DumpUpdate();
203         if (update.empty()) {
204             return;
205         }
206         updateType = UpdateType::PAGE_UPDATE;
207     }
208 
209 #ifdef ACE_DEBUG_LOG
210     auto timeEnd = std::chrono::high_resolution_clock::now();
211     timeStart = timeEnd;
212 #endif
213 
214     if (onUpdateCb_) {
215         onUpdateCb_(updateType, update);
216     }
217 
218 #ifdef ACE_DEBUG_LOG
219     timeEnd = std::chrono::high_resolution_clock::now();
220 #endif
221 }
222 
OnPageChanged(int32_t pageId)223 void DistributedUI::OnPageChanged(int32_t pageId)
224 {
225     if (status_ == StateMachine::SOURCE_START) {
226         pageChangeFlag_ = true;
227     }
228     currentPageId_ = pageId;
229 }
230 
GetCurrentPageId()231 int32_t DistributedUI::GetCurrentPageId()
232 {
233     return currentPageId_;
234 }
235 
BypassEvent(const TouchEvent & point,bool isSubPipe)236 void DistributedUI::BypassEvent(const TouchEvent& point, bool isSubPipe)
237 {
238 #ifdef ACE_DEBUG_LOG
239     auto timeStart = std::chrono::high_resolution_clock::now();
240 #endif
241 
242     std::unique_ptr<JsonValue> json = NodeObject::Create();
243     point.ToJsonValue(json);
244     json->Put("sub", isSubPipe);
245     SerializeableObjectArray eventArray;
246     eventArray.push_back(std::move((std::unique_ptr<NodeObject>&)json));
247 
248 #ifdef ACE_DEBUG_LOG
249     auto timeEnd = std::chrono::high_resolution_clock::now();
250     timeStart = timeEnd;
251 #endif
252 
253     if (onEventCb_) {
254         onEventCb_(eventArray);
255     }
256 
257 #ifdef ACE_DEBUG_LOG
258     timeEnd = std::chrono::high_resolution_clock::now();
259 #endif
260 }
261 
IsSinkMode()262 bool DistributedUI::IsSinkMode()
263 {
264     if (onEventCb_ && status_ == StateMachine::SINK_START) {
265         return true;
266     }
267     return false;
268 }
269 
ApplyOneUpdate()270 void DistributedUI::ApplyOneUpdate()
271 {
272     for (int i = 0; i < HANDLE_UPDATE_PER_VSYNC; i++) {
273         if (pendingUpdates_.empty()) {
274             return;
275         }
276         ResSchedReport::GetInstance().ResSchedDataReport("click");
277         auto update = std::move(pendingUpdates_.front());
278         pendingUpdates_.pop_front();
279         UpdateUITreeInner(update);
280     }
281 }
282 
DumpDirtyRenderNodes(SerializeableObjectArray & objectArray)283 void DistributedUI::DumpDirtyRenderNodes(SerializeableObjectArray& objectArray)
284 {
285     for (const auto& nodeId : dirtyRenderNodes_) {
286         auto node = ElementRegister::GetInstance()->GetUINodeById(nodeId);
287         if (!node || !IsInCurrentPage(node, currentPageId_) || node->GetTag() == V2::PAGE_ETS_TAG) {
288             continue;
289         }
290         if (IsNewNode(nodeId)) {
291             continue;
292         }
293         auto nodeObject = NodeObject::Create();
294         DumpNode(node, -1, OperationType::OP_MODIFY, nodeObject);
295         if (IsRecordHash(nodeId, nodeObject->Hash())) {
296             objectArray.push_back(std::move(nodeObject));
297         }
298     }
299 }
300 
DumpDirtyLayoutNodes(SerializeableObjectArray & objectArray)301 void DistributedUI::DumpDirtyLayoutNodes(SerializeableObjectArray& objectArray)
302 {
303     for (const auto& nodeId : dirtyLayoutNodes_) {
304         auto node = ElementRegister::GetInstance()->GetUINodeById(nodeId);
305         if (!node || !IsInCurrentPage(node, currentPageId_)) {
306             continue;
307         }
308         if (IsNewNode(nodeId)) {
309             continue;
310         }
311         auto nodeObject = NodeObject::Create();
312         DumpNode(node, -1, OperationType::OP_MODIFY, nodeObject);
313         if (IsRecordHash(nodeId, nodeObject->Hash())) {
314             objectArray.push_back(std::move(nodeObject));
315         }
316     }
317 }
318 
DumpNewNodes(SerializeableObjectArray & objectArray)319 void DistributedUI::DumpNewNodes(SerializeableObjectArray& objectArray)
320 {
321     for (const auto& nodeId : newNodes_) {
322         auto node = ElementRegister::GetInstance()->GetUINodeById(nodeId);
323         if (!node || !IsInCurrentPage(node, currentPageId_)) {
324             continue;
325         }
326         auto nodeObject = NodeObject::Create();
327         DumpNode(node, -1, OperationType::OP_ADD, nodeObject);
328         AddNodeHash(nodeId, nodeObject->Hash());
329         objectArray.push_back(std::move(nodeObject));
330     }
331 }
332 
DumpDelNodes(SerializeableObjectArray & objectArray)333 void DistributedUI::DumpDelNodes(SerializeableObjectArray& objectArray)
334 {
335     for (const auto& nodeId : deletedNodes_) {
336         auto nodeObject = NodeObject::Create();
337         nodeObject->Put(DISTRIBUTE_UI_ID, nodeId);
338         nodeObject->Put(DISTRIBUTE_UI_OPERATION, static_cast<int32_t>(OperationType::OP_DELETE));
339         objectArray.push_back(std::move(nodeObject));
340         DelNodeHash(nodeId);
341     }
342 }
343 
DumpUpdate()344 SerializeableObjectArray DistributedUI::DumpUpdate()
345 {
346     if (newNodes_.size() + dirtyRenderNodes_.size() + deletedNodes_.size() + dirtyLayoutNodes_.size() == 0) {
347         return SerializeableObjectArray();
348     }
349     SerializeableObjectArray objectArray;
350 
351     DumpDirtyRenderNodes(objectArray);
352     DumpDirtyLayoutNodes(objectArray);
353     DumpNewNodes(objectArray);
354     DumpDelNodes(objectArray);
355     ResetDirtyNodes();
356     return objectArray;
357 }
358 
ResetDirtyNodes()359 void DistributedUI::ResetDirtyNodes()
360 {
361     newNodes_.clear();
362     dirtyRenderNodes_.clear();
363     deletedNodes_.clear();
364     dirtyLayoutNodes_.clear();
365 }
366 
IsNewNode(int32_t nodeId)367 bool DistributedUI::IsNewNode(int32_t nodeId)
368 {
369     if (newNodes_.find(nodeId) != newNodes_.end()) {
370         return true;
371     }
372     return false;
373 }
374 
ReadyToDumpUpdate()375 bool DistributedUI::ReadyToDumpUpdate()
376 {
377     if (onUpdateCb_ && status_ == StateMachine::SOURCE_START) {
378         return true;
379     }
380     return false;
381 }
382 
SetIdMapping(int32_t srcNodeId,int32_t sinkNodeId)383 void DistributedUI::SetIdMapping(int32_t srcNodeId, int32_t sinkNodeId)
384 {
385     nodeIdMapping_.count(srcNodeId);
386     nodeIdMapping_[srcNodeId] = sinkNodeId;
387 }
388 
GetIdMapping(int32_t srcNodeId)389 int32_t DistributedUI::GetIdMapping(int32_t srcNodeId)
390 {
391     int32_t sinkNodeId = ElementRegister::UndefinedElementId;
392     if (nodeIdMapping_.count(srcNodeId)) {
393         sinkNodeId = nodeIdMapping_[srcNodeId];
394     }
395     return sinkNodeId;
396 }
397 
AddNodeHash(int32_t nodeId,std::size_t hashValue)398 void DistributedUI::AddNodeHash(int32_t nodeId, std::size_t hashValue)
399 {
400     nodeHashs_[nodeId] = hashValue;
401 }
402 
DelNodeHash(int32_t nodeId)403 void DistributedUI::DelNodeHash(int32_t nodeId)
404 {
405     if (nodeHashs_.count(nodeId)) {
406         nodeHashs_.erase(nodeId);
407     }
408 }
409 
IsRecordHash(int32_t nodeId,std::size_t hashValue)410 bool DistributedUI::IsRecordHash(int32_t nodeId, std::size_t hashValue)
411 {
412     if (nodeHashs_.count(nodeId) && nodeHashs_.at(nodeId) == hashValue) {
413         return false;
414     }
415     AddNodeHash(nodeId, hashValue);
416     return true;
417 }
418 
DumpNode(const RefPtr<NG::UINode> & node,int depth,OperationType op,std::unique_ptr<NodeObject> & nodeObject)419 void DistributedUI::DumpNode(
420     const RefPtr<NG::UINode>& node, int depth, OperationType op, std::unique_ptr<NodeObject>& nodeObject)
421 {
422     nodeObject->Put(DISTRIBUTE_UI_TYPE, node->GetTag().c_str());
423     nodeObject->Put(DISTRIBUTE_UI_ID, node->GetId());
424     auto parent = node->GetParent();
425     if (!parent) {
426         nodeObject->Put(DISTRIBUTE_UI_PARENT, -1);
427     } else {
428         nodeObject->Put(DISTRIBUTE_UI_PARENT, parent->GetId());
429     }
430     nodeObject->Put(DISTRIBUTE_UI_DEPTH, depth);
431     nodeObject->Put(DISTRIBUTE_UI_OPERATION, static_cast<int32_t>(op));
432 
433     std::unique_ptr<JsonValue> childObject = NodeObject::Create();
434     node->ToJsonValue(childObject);
435     nodeObject->Put(DISTRIBUTE_UI_ATTRS, (std::unique_ptr<NodeObject>&)childObject);
436 }
437 
DumpTreeInner(const RefPtr<NG::UINode> & node,SerializeableObjectArray & objectArray,int depth)438 void DistributedUI::DumpTreeInner(const RefPtr<NG::UINode>& node, SerializeableObjectArray& objectArray, int depth)
439 {
440     auto nodeObject = NodeObject::Create();
441     DumpNode(node, depth, OperationType::OP_ADD, nodeObject);
442     AddNodeHash(node->GetId(), nodeObject->Hash());
443     objectArray.push_back(std::move(nodeObject));
444 
445     auto children = node->GetChildren();
446     for (const auto& uiNode : children) {
447         DumpTreeInner(uiNode, objectArray, depth + 1);
448     }
449 }
450 
RestoreNode(const std::unique_ptr<NodeObject> & nodeObject)451 RefPtr<UINode> DistributedUI::RestoreNode(const std::unique_ptr<NodeObject>& nodeObject)
452 {
453     static const std::unordered_map<std::string, std::function<RefPtr<UINode>(const std::string&, int32_t)>>
454         nodeCreate {
455             { V2::JS_VIEW_ETS_TAG, [](const std::string& type,
456                                        int32_t nodeId) { return NG::CustomNode::CreateCustomNode(nodeId, type); } },
457             { V2::TEXT_ETS_TAG,
458                 [](const std::string& type, int32_t nodeId) {
459                     return FrameNode::GetOrCreateFrameNode(
460                         type, nodeId, []() { return AceType::MakeRefPtr<TextPattern>(); });
461                 } },
462             { V2::COLUMN_ETS_TAG,
463                 [](const std::string& type, int32_t nodeId) {
464                     return FrameNode::GetOrCreateFrameNode(
465                         type, nodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(true); });
466                 } },
467             { V2::ROW_ETS_TAG,
468                 [](const std::string& type, int32_t nodeId) {
469                     return FrameNode::GetOrCreateFrameNode(
470                         type, nodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
471                 } },
472             { V2::LIST_ITEM_ETS_TAG,
473                 [](const std::string& type, int32_t nodeId) {
474                     return FrameNode::GetOrCreateFrameNode(type, nodeId,
475                         []() { return AceType::MakeRefPtr<ListItemPattern>(nullptr, V2::ListItemStyle::NONE); });
476                 } },
477             { V2::LIST_ETS_TAG,
478                 [](const std::string& type, int32_t nodeId) {
479                     return FrameNode::GetOrCreateFrameNode(
480                         type, nodeId, []() { return AceType::MakeRefPtr<ListPattern>(); });
481                 } },
482             { V2::STACK_ETS_TAG,
483                 [](const std::string& type, int32_t nodeId) {
484                     return FrameNode::GetOrCreateFrameNode(
485                         type, nodeId, []() { return AceType::MakeRefPtr<StackPattern>(); });
486                 } },
487             { V2::IMAGE_ETS_TAG,
488                 [](const std::string& type, int32_t nodeId) {
489                     return FrameNode::GetOrCreateFrameNode(
490                         type, nodeId, []() { return AceType::MakeRefPtr<ImagePattern>(); });
491                 } },
492             { V2::FLEX_ETS_TAG,
493                 [](const std::string& type, int32_t nodeId) {
494                     return FrameNode::GetOrCreateFrameNode(
495                         type, nodeId, []() { return AceType::MakeRefPtr<FlexLayoutPattern>(); });
496                 } },
497             { V2::TABS_ETS_TAG,
498                 [](const std::string& type, int32_t nodeId) {
499                     return TabsModelNG::GetOrCreateTabsNode(
500                         type, nodeId, []() { return AceType::MakeRefPtr<TabsPattern>(); });
501                 } },
502             { V2::TAB_BAR_ETS_TAG,
503                 [](const std::string& type, int32_t nodeId) {
504                     return FrameNode::GetOrCreateFrameNode(
505                         type, nodeId, []() { return AceType::MakeRefPtr<TabBarPattern>(nullptr); });
506                 } },
507             { V2::SWIPER_ETS_TAG,
508                 [](const std::string& type, int32_t nodeId) {
509                     return FrameNode::GetOrCreateFrameNode(
510                         type, nodeId, []() { return AceType::MakeRefPtr<SwiperPattern>(); });
511                 } },
512             { V2::TAB_CONTENT_ITEM_ETS_TAG,
513                 [](const std::string& type, int32_t nodeId) {
514                     return TabContentNode::GetOrCreateTabContentNode(
515                         type, nodeId, []() { return AceType::MakeRefPtr<TabContentPattern>(nullptr); });
516                 } },
517             { V2::COMMON_VIEW_ETS_TAG,
518                 [](const std::string& type, int32_t nodeId) {
519                     return FrameNode::GetOrCreateFrameNode(
520                         type, nodeId, []() { return AceType::MakeRefPtr<CommonViewPattern>(); });
521                 } },
522             { V2::JS_FOR_EACH_ETS_TAG,
523                 [](const std::string& type, int32_t nodeId) { return ForEachNode::GetOrCreateForEachNode(nodeId); } },
524             { V2::JS_SYNTAX_ITEM_ETS_TAG,
525                 [](const std::string& type, int32_t nodeId) { return SyntaxItem::CreateSyntaxItemNode(type); } },
526             { V2::JS_LAZY_FOR_EACH_ETS_TAG,
527                 [](const std::string& type, int32_t nodeId) {
528                     return LazyForEachNode::GetOrCreateLazyForEachNode(nodeId, nullptr);
529                 } },
530             { V2::JS_IF_ELSE_ETS_TAG,
531                 [](const std::string& type, int32_t nodeId) { return IfElseNode::GetOrCreateIfElseNode(nodeId); } },
532             { V2::TEXTINPUT_ETS_TAG,
533                 [](const std::string& type, int32_t nodeId) {
534                     return FrameNode::GetOrCreateFrameNode(
535                         type, nodeId, []() { return AceType::MakeRefPtr<TextFieldPattern>(); });
536                 } },
537             { V2::DIVIDER_ETS_TAG,
538                 [](const std::string& type, int32_t nodeId) {
539                     return FrameNode::GetOrCreateFrameNode(
540                         type, nodeId, []() { return AceType::MakeRefPtr<DividerPattern>(); });
541                 } },
542         };
543 
544     auto type = nodeObject->GetString(DISTRIBUTE_UI_TYPE);
545     auto srcNodeId = nodeObject->GetInt(DISTRIBUTE_UI_ID);
546     auto srcParentNodeId = nodeObject->GetInt(DISTRIBUTE_UI_PARENT);
547     auto depth = nodeObject->GetInt(DISTRIBUTE_UI_DEPTH);
548 
549     if (!nodeCreate.count(type)) {
550         LOGE("UITree |ERROR| found no type %{public}s id %{public}d pid %{public}d depth %{public}d", type.c_str(),
551             srcNodeId, srcParentNodeId, depth);
552         return nullptr;
553     }
554 
555     if (!nodeObject->Contains(DISTRIBUTE_UI_ATTRS)) {
556         LOGW("UITree |ERROR| found no attrs");
557         return nullptr;
558     }
559     auto attrs = nodeObject->GetValue(DISTRIBUTE_UI_ATTRS);
560 
561     auto sinkNodeId = srcNodeId == -1 ? -1 : ElementRegister::GetInstance()->MakeUniqueId();
562     if (ElementRegister::GetInstance()->GetUINodeById(sinkNodeId)) {
563         return nullptr;
564     }
565 
566     RefPtr<UINode> uiNode = nullptr;
567     if (type == V2::JS_VIEW_ETS_TAG) {
568         uiNode = nodeCreate.at(type)(attrs->GetString("viewKey"), sinkNodeId);
569     } else if (type == V2::JS_SYNTAX_ITEM_ETS_TAG) {
570         uiNode = nodeCreate.at(type)(attrs->GetString("key"), sinkNodeId);
571     } else {
572         uiNode = nodeCreate.at(type)(type, sinkNodeId);
573     }
574     if (!uiNode) {
575         return nullptr;
576     }
577 
578     SetIdMapping(srcNodeId, uiNode->GetId());
579     uiNode->FromJson(attrs);
580 
581     if (type == V2::IMAGE_ETS_TAG) {
582         AceType::DynamicCast<NG::FrameNode>(uiNode)->MarkModifyDone();
583     }
584 
585     return uiNode;
586 }
587 
AttachToTree(RefPtr<UINode> root,RefPtr<UINode> uiNode,const std::unique_ptr<NodeObject> & nodeObject)588 void DistributedUI::AttachToTree(
589     RefPtr<UINode> root, RefPtr<UINode> uiNode, const std::unique_ptr<NodeObject>& nodeObject)
590 {
591     auto depth = nodeObject->GetInt(DISTRIBUTE_UI_DEPTH);
592     auto sinkParentNodeId = GetIdMapping(nodeObject->GetInt(DISTRIBUTE_UI_PARENT));
593 
594     if (depth == 1) {
595         root->AddChild(uiNode);
596     } else {
597         auto parent = ElementRegister::GetInstance()->GetUINodeById(sinkParentNodeId);
598         if (!parent) {
599             return;
600         }
601         parent->AddChild(uiNode);
602         parent->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
603     }
604 }
605 
AddNode(const std::unique_ptr<NodeObject> & nodeObject,RefPtr<FrameNode> pageRootNode)606 void DistributedUI::AddNode(const std::unique_ptr<NodeObject>& nodeObject, RefPtr<FrameNode> pageRootNode)
607 {
608     auto uiNode = RestoreNode(nodeObject);
609     if (!uiNode) {
610         return;
611     }
612     AttachToTree(pageRootNode, uiNode, nodeObject);
613 }
614 
ModNode(const std::unique_ptr<NodeObject> & nodeObject)615 void DistributedUI::ModNode(const std::unique_ptr<NodeObject>& nodeObject)
616 {
617     auto sinkNodeId = GetIdMapping(nodeObject->GetInt(DISTRIBUTE_UI_ID));
618     auto sinkNode = ElementRegister::GetInstance()->GetUINodeById(sinkNodeId);
619     if (!sinkNode) {
620         return;
621     }
622     auto attrs = nodeObject->GetValue(DISTRIBUTE_UI_ATTRS);
623     sinkNode->FromJson(attrs);
624     sinkNode->MarkDirtyNode();
625 }
626 
DelNode(const std::unique_ptr<NodeObject> & nodeObject)627 void DistributedUI::DelNode(const std::unique_ptr<NodeObject>& nodeObject)
628 {
629     auto sinkNodeId = GetIdMapping(nodeObject->GetInt(DISTRIBUTE_UI_ID));
630     auto sinkNode = ElementRegister::GetInstance()->GetUINodeById(sinkNodeId);
631     if (!sinkNode) {
632         return;
633     }
634     auto parent = sinkNode->GetParent();
635     if (!parent) {
636         return;
637     }
638     parent->RemoveChild(sinkNode);
639     parent->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
640 }
641 
UpdateUITreeInner(SerializeableObjectArray & nodeArray)642 void DistributedUI::UpdateUITreeInner(SerializeableObjectArray& nodeArray)
643 {
644     auto context = NG::PipelineContext::GetCurrentContext();
645     CHECK_NULL_VOID(context);
646     auto pageRootNode = context->GetStageManager()->GetLastPage();
647     CHECK_NULL_VOID(pageRootNode);
648 
649     for (const auto& nodeObject : nodeArray) {
650         OperationType op = static_cast<OperationType>(nodeObject->GetInt(DISTRIBUTE_UI_OPERATION));
651         if (op == OperationType::OP_ADD) {
652             AddNode((std::unique_ptr<NodeObject>&)nodeObject, pageRootNode);
653         } else if (op == OperationType::OP_MODIFY) {
654             ModNode((std::unique_ptr<NodeObject>&)nodeObject);
655         } else if (op == OperationType::OP_DELETE) {
656             DelNode((std::unique_ptr<NodeObject>&)nodeObject);
657         }
658     }
659 
660     context->RequestFrame();
661 }
662 
RestoreUITreeInner(const SerializeableObjectArray & nodeArray)663 void DistributedUI::RestoreUITreeInner(const SerializeableObjectArray& nodeArray)
664 {
665     if (nodeArray.empty()) {
666         return;
667     }
668 
669     auto context = NG::PipelineContext::GetCurrentContext();
670     CHECK_NULL_VOID(context);
671     auto pageRootNode = context->GetStageManager()->GetLastPage();
672     CHECK_NULL_VOID(pageRootNode);
673     RestorePageNode(pageRootNode);
674     sinkPageChildren_ = pageRootNode->GetChildren();
675     for (const auto& child : sinkPageChildren_) {
676         pageRootNode->RemoveChild(child);
677     }
678 
679     for (const auto& nodeObject : nodeArray) {
680         AddNode((std::unique_ptr<NodeObject>&)nodeObject, pageRootNode);
681     }
682 
683     pageRootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
684 }
685 
IsInCurrentPage(RefPtr<NG::UINode> node,int32_t pageId)686 bool DistributedUI::IsInCurrentPage(RefPtr<NG::UINode> node, int32_t pageId)
687 {
688     if (node->GetTag() == V2::JS_SYNTAX_ITEM_ETS_TAG) {
689         return true;
690     }
691     if (pageId != 0 && node->GetPageId() != pageId) {
692         return false;
693     }
694     return true;
695 }
696 } // namespace OHOS::Ace::NG
697