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