• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include "tree_manager.h"
16 
17 #include "accessibility_ui_test_ability.h"
18 #include "component_manager.h"
19 #include "touch_input.h"
20 
21 namespace OHOS {
22 namespace WuKong {
23 namespace {
24 class ComponentManagerMonitor : public ComponentManagerListener {
OnStatusUpdated(ComponentStatus status)25     void OnStatusUpdated(ComponentStatus status) override
26     {
27     }
OnScreenUpdated()28     void OnScreenUpdated() override
29     {
30     }
OnPermissionScreenShown()31     void OnPermissionScreenShown() override
32     {
33     }
34 };
35 }  // namespace
36 
TreeManager()37 TreeManager::TreeManager() : isUpdateComponentFinished_(false), isNewAbility_(false)
38 {
39 }
~TreeManager()40 TreeManager::~TreeManager()
41 {
42     TRACK_LOG_STD();
43 }
44 
RecursGetChildElementInfo(const std::shared_ptr<OHOS::Accessibility::AccessibilityElementInfo> & parent,const std::shared_ptr<ComponentTree> & componentParent)45 bool TreeManager::RecursGetChildElementInfo(
46     const std::shared_ptr<OHOS::Accessibility::AccessibilityElementInfo>& parent,
47     const std::shared_ptr<ComponentTree>& componentParent)
48 {
49     auto res = Accessibility::RET_OK;
50     if (componentParent == nullptr) {
51         ERROR_LOG("tree parent is null!");
52         return false;
53     }
54     for (int32_t i = 0; i < parent->GetChildCount(); i++) {
55         auto elementChild = std::make_shared<OHOS::Accessibility::AccessibilityElementInfo>();
56         // Get child AccessibilityElementInfo from Accessibility.
57         res = OHOS::Accessibility::AccessibilityUITestAbility::GetInstance()->GetChildElementInfo(
58             i, *(parent.get()), *(elementChild.get()));
59         if (res != Accessibility::RET_OK) {
60             ERROR_LOG("GetChildElementInfo failed!");
61             return false;
62         }
63         TRACK_LOG_STR("GetChildElementInfo child ID (%d), child count (%d), Type (%s)",
64                       elementChild->GetAccessibilityId(), elementChild->GetChildCount(),
65                       elementChild->GetComponentType().c_str());
66 
67         // save child AccessibilityElementInfo.
68         newElementInfoList_.push_back(elementChild);
69 
70         // Generate ComponentTree.
71         std::shared_ptr<ComponentTree> componentChild = std::make_shared<ComponentTree>();
72         componentChild->SetIndex(newElementInfoList_.size() - 1);
73         // set ComponentTree parent
74         componentChild->SetParent(componentParent);
75         componentParent->AddChild(componentChild);
76         // Recurs get child AccessibilityElementInfo.
77         auto result = RecursGetChildElementInfo(elementChild, componentChild);
78         if (!result) {
79             return false;
80         }
81     }
82 
83     componentParent->SetNodeId();
84     return res == Accessibility::RET_OK ? true : false;
85 }
RecursComponent(const std::shared_ptr<ComponentTree> & componentTree)86 bool TreeManager::RecursComponent(const std::shared_ptr<ComponentTree>& componentTree)
87 {
88     if (LOG_LEVEL_TRACK < WuKongLogger::GetInstance()->GetLogLevel()) {
89         return false;
90     }
91     if (componentTree == nullptr) {
92         return false;
93     }
94     auto children = componentTree->GetChildren();
95 
96     auto elementInfo = GetNewElementInfoList(componentTree->GetIndex());
97     if (elementInfo != nullptr) {
98         TRACK_LOG_STR("Component Node Indxe:(%d), NodeId:(0x%016llX), input count:(%u), Element ID(%d), Type(%s)",
99                       componentTree->GetIndex(), componentTree->GetNodeId(), componentTree->GetInputCount(),
100                       elementInfo->GetAccessibilityId(), elementInfo->GetComponentType().c_str());
101     } else {
102         TRACK_LOG_STR("Component Node Indxe:(%d), NodeId:(0x%016llX), input count:(%u)", componentTree->GetIndex(),
103                       componentTree->GetNodeId(), componentTree->GetInputCount());
104     }
105 
106     for (auto tree : children) {
107         RecursComponent(std::static_pointer_cast<ComponentTree>(tree));
108     }
109     return true;
110 }
111 
FindAbility(const std::shared_ptr<AbilityTree> & abilityNode)112 bool TreeManager::FindAbility(const std::shared_ptr<AbilityTree>& abilityNode)
113 {
114     if (newAbilityNode_->IsEqual(abilityNode)) {
115         DEBUG_LOG("Found same old ability");
116         currentAbilityNode_ = abilityNode;
117         return true;
118     } else {
119         for (auto child : abilityNode->GetChildren()) {
120             if (FindAbility(std::static_pointer_cast<AbilityTree>(child))) {
121                 return true;
122             }
123         }
124         return false;
125     }
126 }
127 
MakeAndCheckNewAbility()128 ErrCode TreeManager::MakeAndCheckNewAbility()
129 {
130     // Check ability state
131     newAbilityNode_ = std::make_shared<AbilityTree>();
132     newAbilityNode_->SetNodeId();
133     // check same abiliby as current ability
134     if (currentAbilityNode_ != nullptr) {
135         if (newAbilityNode_->IsEqual(currentAbilityNode_)) {
136             DEBUG_LOG("Ability not change");
137             return OHOS::ERR_OK;
138         }
139     } else if (currentAbilityNode_ == nullptr) {
140         return OHOS::ERR_INVALID_OPERATION;
141     }
142 
143     DEBUG_LOG("Ability changed");
144     bool isNewBundle = true;
145     bool isNewAbility = false;
146     for (auto abilityTree : abilityTreeList_) {
147         TRACK_LOG_STR("NewAbility Bundle: (%s), Bundle List Name: (%s)", newAbilityNode_->bundleName_.c_str(),
148                       abilityTree->bundleName_.c_str());
149         // check is new bundle.
150         if (abilityTree->bundleName_ == newAbilityNode_->bundleName_) {
151             isNewBundle = false;
152             // find new ability in ability tree.
153             if (!FindAbility(abilityTree)) {
154                 currentAbilityNode_->AddChild(newAbilityNode_);
155                 newAbilityNode_->SetParent(currentAbilityNode_);
156                 currentAbilityNode_ = newAbilityNode_;
157                 isNewAbility = true;
158             }
159         }
160     }
161     // save new bundle for launch multi-application
162     if (isNewBundle) {
163         InitContainer();
164         abilityTreeList_.push_back(newAbilityNode_);
165         currentAbilityNode_ = newAbilityNode_;
166     }
167     // clear current screen data when it is new ability.
168     if (isNewBundle || isNewAbility) {
169         currentComponentNode_ = nullptr;
170         currentPageNode_ = nullptr;
171         isNewAbility_ = true;
172     } else {
173         // set old screen to current screen data when it is old ability.
174         if (pageTreeList_.find(currentAbilityNode_->GetIndex()) == pageTreeList_.end()) {
175             ERROR_LOG_STR("ability index (%d) more than pageTreeList count (%d)", currentAbilityNode_->GetIndex(),
176                           pageTreeList_.size());
177             return OHOS::ERR_INVALID_OPERATION;
178         }
179         currentPageNode_ = pageTreeList_[currentAbilityNode_->GetIndex()];
180         if (componentTreeList_.find(currentPageNode_->GetIndex()) == componentTreeList_.end()) {
181             ERROR_LOG_STR("page index (%d) more than componentTreeList count (%d)", currentPageNode_->GetIndex(),
182                           componentTreeList_.size());
183             return OHOS::ERR_INVALID_OPERATION;
184         }
185         currentComponentNode_ = componentTreeList_[currentPageNode_->GetIndex()];
186     }
187     return OHOS::ERR_OK;
188 }
189 
UpdateComponentInfo()190 ErrCode TreeManager::UpdateComponentInfo()
191 {
192     TRACK_LOG_STD();
193     ErrCode result = OHOS::ERR_OK;
194     // start update component tree.
195     isUpdateComponentFinished_ = false;
196     isNewAbility_ = false;
197     newElementInfoList_.clear();
198     if (WuKongLogger::GetInstance()->GetLogLevel() == LOG_LEVEL_TRACK) {
199         DEBUG_LOG_STR("CompoentNode shared  new (%p) count = (%ld) unique (%d)", newComponentNode_.get(),
200                       newComponentNode_.use_count(), newComponentNode_.unique());
201         DEBUG_LOG_STR("CompoentNode shared (%p) count = (%ld) unique (%d)", currentComponentNode_.get(),
202                       currentComponentNode_.use_count(), currentComponentNode_.unique());
203     }
204     // Generate Ability Node
205     MakeAndCheckNewAbility();
206 
207     auto root = std::make_shared<OHOS::Accessibility::AccessibilityElementInfo>();
208     auto aacPtr = OHOS::Accessibility::AccessibilityUITestAbility::GetInstance();
209 
210     // Get root AccessibilityElementInfo from Accessibility,
211     auto bResult = aacPtr->GetRoot(*(root.get()));
212     if (bResult != Accessibility::RET_OK) {
213         ERROR_LOG("Accessibility Ability get root element info failed!");
214         return OHOS::ERR_INVALID_OPERATION;
215     } else {
216         // save root AccessibilityElementInfo.
217         newElementInfoList_.push_back(root);
218         uint32_t count = newElementInfoList_.size();
219         DEBUG_LOG_STR("New Element Info count (%d), Type (%s)", root->GetChildCount(),
220                       root->GetComponentType().c_str());
221 
222         // Generate new ComponentTree.
223         newComponentNode_ = std::make_shared<ComponentTree>();
224         newComponentNode_->SetIndex(count - 1);
225 
226         // Recurs get all children AccessibilityElementInfo.
227         auto cResult = RecursGetChildElementInfo(root, newComponentNode_);
228         if (!cResult) {
229             return OHOS::ERR_INVALID_OPERATION;
230         }
231         RecursComponent(newComponentNode_);
232     }
233     // Generate Page Node
234     newPageNode_ = std::make_shared<PageTree>();
235     newPageNode_->SetNodeId();
236 
237     TRACK_LOG_END();
238     return result;
239 }
240 
SetInputcomponentIndex(int actionType,uint32_t index)241 void TreeManager::SetInputcomponentIndex(int actionType, uint32_t index)
242 {
243     DEBUG_LOG_STR("Input: (%d), Input Type: (%d)", index, actionType);
244     if (currentPageNode_ == nullptr) {
245         ERROR_LOG("current page is null!");
246         return;
247     }
248 
249     // component input count statistics
250     if (index != INVALIDED_INPUT_INDEX) {
251         if (inputComponentList_.size() <= 0) {
252             ERROR_LOG("input component list is null!");
253             return;
254         }
255         if (index >= inputComponentList_.size()) {
256             ERROR_LOG("index argument is invalided");
257             return;
258         }
259         inputComponentList_[index]->AddInputCount();
260         inputComponentList_[index]->AddTypeInputCount(actionType);
261         DEBUG_LOG_STR("inputComponent: GetNodeId (0x%016llX)", inputComponentList_[index]->GetNodeId());
262     } else {
263         if (inputComponent_ == nullptr) {
264             ERROR_LOG("inputComponent_ is nullptr");
265             return;
266         }
267         inputComponent_->AddInputCount();
268         inputComponent_->AddTypeInputCount(actionType);
269         DEBUG_LOG_STR("inputComponent: GetNodeId (0x%016llX)", inputComponent_->GetNodeId());
270     }
271     RecursComponent(currentComponentNode_);
272     // ability input count statistics
273     currentAbilityNode_->AddInputCount();
274 
275     // page input count statistics
276     currentPageNode_->AddInputCount();
277     if (index != INVALIDED_INPUT_INDEX) {
278         currentPageNode_->SetCurrentComponentNode(inputComponentList_[index]);
279     } else {
280         currentPageNode_->SetCurrentComponentNode(inputComponent_);
281     }
282 }
283 
SetActiveComponent(const std::vector<std::shared_ptr<ComponentTree>> & inputComponentList)284 void TreeManager::SetActiveComponent(const std::vector<std::shared_ptr<ComponentTree>>& inputComponentList)
285 {
286     DEBUG_LOG_STR("Active component list: size (%d)", inputComponentList.size());
287     // Clear old input data
288     inputElementInfoList_.clear();
289     inputComponentList_.clear();
290     uint32_t count = elementInfoList_.size();
291     for (auto componentNode : inputComponentList) {
292         if (count > componentNode->GetIndex()) {
293             // Save input pointer list
294             inputElementInfoList_.push_back(elementInfoList_[componentNode->GetIndex()]);
295             inputComponentList_.push_back(componentNode);
296         } else {
297             ERROR_LOG_STR("component index (%d) more than elementInfoList count (%d)", componentNode->GetIndex(),
298                           count);
299             break;
300         }
301     }
302 }
303 
SetActiveComponent(const std::shared_ptr<ComponentTree> & inputComponent)304 void TreeManager::SetActiveComponent(const std::shared_ptr<ComponentTree>& inputComponent)
305 {
306     // Save one input pointer.
307     if (inputComponent == nullptr) {
308         ERROR_LOG("argument failed inputComponent is nullptr");
309         return;
310     }
311     DEBUG_LOG_STR("Active component: GetNodeId (0x%016llX)", inputComponent->GetNodeId());
312     inputComponent_ = inputComponent;
313     if (elementInfoList_.size() > inputComponent->GetIndex()) {
314         inputElementInfo_ = elementInfoList_[inputComponent->GetIndex()];
315     } else {
316         ERROR_LOG_STR("component index (%d) more than elementInfoList count (%d)", inputComponent->GetIndex(),
317                       elementInfoList_.size());
318     }
319 }
320 
AddPage()321 bool TreeManager::AddPage()
322 {
323     TRACK_LOG_STD();
324     // save new component tree, and change current conmponent tree.
325     UpdateCurrentPage(true);
326 
327     // page tree growth
328     if (newPageNode_ == nullptr) {
329         ERROR_LOG("the new Page Node is null");
330         return false;
331     }
332 
333     uint32_t key = componentTreeList_.size();
334     componentTreeList_[key] = currentComponentNode_;
335     newPageNode_->SetIndex(key);
336     if (!isNewAbility_) {
337         if (currentPageNode_ != nullptr) {
338             newPageNode_->SetParent(currentPageNode_);
339             currentPageNode_->AddChild(newPageNode_);
340         }
341     } else {
342         // ability tree growth
343         key = pageTreeList_.size();
344         pageTreeList_[key] = newPageNode_;
345         currentAbilityNode_->SetIndex(key);
346     }
347     currentPageNode_ = newPageNode_;
348     currentAbilityNode_->AddAllComponentCount(currentPageNode_->GetAllComponentCount());
349 
350     TRACK_LOG_END();
351     return SamePage();
352 }
353 
SamePage()354 bool TreeManager::SamePage()
355 {
356     TRACK_LOG_STD();
357     isUpdateComponentFinished_ = true;
358     newElementInfoList_.clear();
359     if (WuKongLogger::GetInstance()->GetLogLevel() == LOG_LEVEL_TRACK) {
360         DEBUG_LOG_STR("CompoentNode shared  new (%p) count = (%ld) unique (%d)", newComponentNode_.get(),
361                       newComponentNode_.use_count(), newComponentNode_.unique());
362     }
363     newComponentNode_.reset();
364     newPageNode_.reset();
365     newAbilityNode_.reset();
366     TRACK_LOG_END();
367     return true;
368 }
369 
UpdatePage(int layer,uint32_t index)370 bool TreeManager::UpdatePage(int layer, uint32_t index)
371 {
372     TRACK_LOG_STD();
373     DEBUG_LOG_STR("UpdatePage: layer (%d), index (%u)", layer, index);
374     std::shared_ptr<WuKongTree> pageNode = currentPageNode_;
375     if (layer > 0) {
376         if (pageNode->GetChildren().size() <= index) {
377             ERROR_LOG_STR("UpdatePage child index (%d) more than elementInfoList_ GetChildren() size (%u)", index,
378                           pageNode->GetChildren().size());
379             return false;
380         }
381         currentPageNode_ = std::static_pointer_cast<PageTree>(pageNode->GetChildren()[index]);
382     } else {
383         while (layer < 0) {
384             layer++;
385             pageNode = pageNode->GetParent();
386             if (pageNode == nullptr) {
387                 ERROR_LOG_STR("UpdatePage back layer (%d) more than currentPageNode_ parent (%p)", layer,
388                               pageNode.get());
389                 return false;
390             }
391         }
392         currentPageNode_ = std::static_pointer_cast<PageTree>(pageNode);
393     }
394 
395     if (componentTreeList_.find(currentPageNode_->GetIndex()) == componentTreeList_.end()) {
396         ERROR_LOG_STR("currentPageNode_ index (%u) more than componentTreeList_ size (%u)",
397                       currentPageNode_->GetIndex(), componentTreeList_.size());
398         return false;
399     }
400 
401     TRACK_LOG_STR("currentPageNode_->GetIndex(): %d", currentPageNode_->GetIndex());
402     currentComponentNode_ = componentTreeList_[currentPageNode_->GetIndex()];
403 
404     if (!UpdateCurrentPage()) {
405         return false;
406     }
407     TRACK_LOG_END();
408     return SamePage();
409 }
410 
RemovePage()411 bool TreeManager::RemovePage()
412 {
413     TRACK_LOG_STD();
414     uint32_t componentNodeIndex = currentPageNode_->GetIndex();
415     uint32_t componentTreeListCount = componentTreeList_.size();
416     if (componentNodeIndex >= componentTreeListCount) {
417         ERROR_LOG_STR("currentPageNode index (%u) more than componentTreeList_ size (%u)", componentNodeIndex,
418                       componentTreeListCount);
419         return false;
420     }
421     if (WuKongLogger::GetInstance()->GetLogLevel() == LOG_LEVEL_TRACK) {
422         DEBUG_LOG_STR("CompoentNode shared (%p) count = (%ld) unique (%d)",
423                       componentTreeList_[componentNodeIndex].get(), componentTreeList_[componentNodeIndex].use_count(),
424                       componentTreeList_[componentNodeIndex].unique());
425     }
426     auto componentNode = componentTreeList_[componentNodeIndex];
427     if (componentNode == nullptr) {
428         ERROR_LOG("componentNode point is nullptr of currentPageNode");
429         return false;
430     }
431     uint32_t startIndex = componentNode->GetIndex();
432     componentTreeList_[componentNodeIndex].reset();
433     uint32_t endIndex = startIndex + currentPageNode_->count_ - 1;
434     uint32_t elementInfoListCount = elementInfoList_.size();
435     DEBUG_LOG_STR(
436         "currentPageNode StartIndex (%u) EndIndex (%u) componentTreeList_ size (%u) elementInfoList_ size (%u)",
437         startIndex, endIndex, componentTreeListCount, elementInfoListCount);
438     if (startIndex >= elementInfoListCount || endIndex >= elementInfoListCount) {
439         ERROR_LOG_STR("currentPageNode StartIndex (%u) EndIndex (%u) more than elementInfoList_ size (%u)", startIndex,
440                       endIndex, elementInfoListCount);
441         return false;
442     }
443     elementInfoList_.erase(elementInfoList_.begin() + startIndex, elementInfoList_.begin() + endIndex);
444     TRACK_LOG_END();
445     return true;
446 }
447 
UpdateCurrentPage(bool isAdd)448 bool TreeManager::UpdateCurrentPage(bool isAdd)
449 {
450     TRACK_LOG_STD();
451     uint32_t count = elementInfoList_.size();
452     DEBUG_LOG_STR("elementInfoList_: %d", count);
453     for (auto elementInfo : newElementInfoList_) {
454         elementInfoList_.push_back(elementInfo);
455     }
456     if (WuKongLogger::GetInstance()->GetLogLevel() == LOG_LEVEL_TRACK) {
457         DEBUG_LOG_STR("CompoentNode shared  new (%p) count = (%ld) unique (%d)", newComponentNode_.get(),
458                       newComponentNode_.use_count(), newComponentNode_.unique());
459         DEBUG_LOG_STR("CompoentNode shared (%p) count = (%ld) unique (%d)", currentComponentNode_.get(),
460                       currentComponentNode_.use_count(), currentComponentNode_.unique());
461     }
462     // update component tree index
463     newComponentNode_->RecursUpdateNodeIndex(count);
464     if (!isAdd) {
465         newComponentNode_->RecursUpdateInfo(currentComponentNode_);
466     }
467     // set current sreen componentNode to new screen
468     currentComponentNode_ = newComponentNode_;
469     if (WuKongLogger::GetInstance()->GetLogLevel() == LOG_LEVEL_TRACK) {
470         DEBUG_LOG_STR("CompoentNode shared (%p) count = (%ld) unique (%d)", currentComponentNode_.get(),
471                       currentComponentNode_.use_count(), currentComponentNode_.unique());
472         if (currentPageNode_ != nullptr) {
473             DEBUG_LOG_STR("CompoentNode shared (%p) index (%u) count = (%ld) unique (%d)",
474                           componentTreeList_[currentPageNode_->GetIndex()].get(), currentPageNode_->GetIndex(),
475                           componentTreeList_[currentPageNode_->GetIndex()].use_count(),
476                           componentTreeList_[currentPageNode_->GetIndex()].unique());
477         }
478     }
479 
480     if (!isAdd) {
481         componentTreeList_[currentPageNode_->GetIndex()] = currentComponentNode_;
482         currentAbilityNode_->allComponentCount_ -= currentPageNode_->GetAllComponentCount();
483         currentAbilityNode_->allComponentCount_ += newPageNode_->GetAllComponentCount();
484         currentPageNode_->nodeId_ = newPageNode_->nodeId_;
485         currentPageNode_->allComponentCount_ = newPageNode_->allComponentCount_;
486     }
487     TRACK_LOG_END();
488     return true;
489 }
490 }  // namespace WuKong
491 }  // namespace OHOS
492