• 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         abilityTreeList_.push_back(newAbilityNode_);
164         currentAbilityNode_ = newAbilityNode_;
165     }
166     // clear current screen data when it is new ability.
167     if (isNewBundle || isNewAbility) {
168         currentComponentNode_ = nullptr;
169         currentPageNode_ = nullptr;
170         isNewAbility_ = true;
171     } else {
172         // set old screen to current screen data when it is old ability.
173         if (pageTreeList_.find(currentAbilityNode_->GetIndex()) == pageTreeList_.end()) {
174             ERROR_LOG_STR("ability index (%d) more than pageTreeList count (%d)", currentAbilityNode_->GetIndex(),
175                           pageTreeList_.size());
176             return OHOS::ERR_INVALID_OPERATION;
177         }
178         currentPageNode_ = pageTreeList_[currentAbilityNode_->GetIndex()];
179         if (componentTreeList_.find(currentPageNode_->GetIndex()) == componentTreeList_.end()) {
180             ERROR_LOG_STR("page index (%d) more than componentTreeList count (%d)", currentPageNode_->GetIndex(),
181                           componentTreeList_.size());
182             return OHOS::ERR_INVALID_OPERATION;
183         }
184         currentComponentNode_ = componentTreeList_[currentPageNode_->GetIndex()];
185     }
186     return OHOS::ERR_OK;
187 }
188 
UpdateComponentInfo()189 ErrCode TreeManager::UpdateComponentInfo()
190 {
191     TRACK_LOG_STD();
192     ErrCode result = OHOS::ERR_OK;
193     // start update component tree.
194     isUpdateComponentFinished_ = false;
195     isNewAbility_ = false;
196     newElementInfoList_.clear();
197     if (WuKongLogger::GetInstance()->GetLogLevel() == LOG_LEVEL_TRACK) {
198         DEBUG_LOG_STR("CompoentNode shared  new (%p) count = (%ld) unique (%d)", newComponentNode_.get(),
199                       newComponentNode_.use_count(), newComponentNode_.unique());
200         DEBUG_LOG_STR("CompoentNode shared (%p) count = (%ld) unique (%d)", currentComponentNode_.get(),
201                       currentComponentNode_.use_count(), currentComponentNode_.unique());
202     }
203     // Generate Ability Node
204     MakeAndCheckNewAbility();
205 
206     auto root = std::make_shared<OHOS::Accessibility::AccessibilityElementInfo>();
207     auto aacPtr = OHOS::Accessibility::AccessibilityUITestAbility::GetInstance();
208 
209     // Get root AccessibilityElementInfo from Accessibility,
210     auto bResult = aacPtr->GetRoot(*(root.get()));
211     if (bResult != Accessibility::RET_OK) {
212         ERROR_LOG("Accessibility Ability get root element info failed!");
213         return OHOS::ERR_INVALID_OPERATION;
214     } else {
215         // save root AccessibilityElementInfo.
216         newElementInfoList_.push_back(root);
217         uint32_t count = newElementInfoList_.size();
218         DEBUG_LOG_STR("New Element Info count (%d), Type (%s)", root->GetChildCount(),
219                       root->GetComponentType().c_str());
220 
221         // Generate new ComponentTree.
222         newComponentNode_ = std::make_shared<ComponentTree>();
223         newComponentNode_->SetIndex(count - 1);
224 
225         // Recurs get all children AccessibilityElementInfo.
226         auto cResult = RecursGetChildElementInfo(root, newComponentNode_);
227         if (!cResult) {
228             return OHOS::ERR_INVALID_OPERATION;
229         }
230         RecursComponent(newComponentNode_);
231     }
232     // Generate Page Node
233     newPageNode_ = std::make_shared<PageTree>();
234     newPageNode_->SetNodeId();
235 
236     TRACK_LOG_END();
237     return result;
238 }
239 
SetInputcomponentIndex(int actionType,uint32_t index)240 void TreeManager::SetInputcomponentIndex(int actionType, uint32_t index)
241 {
242     DEBUG_LOG_STR("Input: (%d), Input Type: (%d)", index, actionType);
243     if (currentPageNode_ == nullptr) {
244         ERROR_LOG("current page is null!");
245         return;
246     }
247 
248     // component input count statistics
249     if (index != INVALIDED_INPUT_INDEX) {
250         if (inputComponentList_.size() <= 0) {
251             ERROR_LOG("input component list is null!");
252             return;
253         }
254         if (index >= inputComponentList_.size()) {
255             ERROR_LOG("index argument is invalided");
256             return;
257         }
258         inputComponentList_[index]->AddInputCount();
259         inputComponentList_[index]->AddTypeInputCount(actionType);
260         DEBUG_LOG_STR("inputComponent: GetNodeId (0x%016llX)", inputComponentList_[index]->GetNodeId());
261     } else {
262         if (inputComponent_ == nullptr) {
263             ERROR_LOG("inputComponent_ is nullptr");
264             return;
265         }
266         inputComponent_->AddInputCount();
267         inputComponent_->AddTypeInputCount(actionType);
268         DEBUG_LOG_STR("inputComponent: GetNodeId (0x%016llX)", inputComponent_->GetNodeId());
269     }
270     RecursComponent(currentComponentNode_);
271     // ability input count statistics
272     currentAbilityNode_->AddInputCount();
273 
274     // page input count statistics
275     currentPageNode_->AddInputCount();
276     if (index != INVALIDED_INPUT_INDEX) {
277         currentPageNode_->SetCurrentComponentNode(inputComponentList_[index]);
278     } else {
279         currentPageNode_->SetCurrentComponentNode(inputComponent_);
280     }
281 }
282 
SetActiveComponent(const std::vector<std::shared_ptr<ComponentTree>> & inputComponentList)283 void TreeManager::SetActiveComponent(const std::vector<std::shared_ptr<ComponentTree>>& inputComponentList)
284 {
285     DEBUG_LOG_STR("Active component list: size (%d)", inputComponentList.size());
286     // Clear old input data
287     inputElementInfoList_.clear();
288     inputComponentList_.clear();
289     uint32_t count = elementInfoList_.size();
290     for (auto componentNode : inputComponentList) {
291         if (count > componentNode->GetIndex()) {
292             // Save input pointer list
293             inputElementInfoList_.push_back(elementInfoList_[componentNode->GetIndex()]);
294             inputComponentList_.push_back(componentNode);
295         } else {
296             ERROR_LOG_STR("component index (%d) more than elementInfoList count (%d)", componentNode->GetIndex(),
297                           count);
298             break;
299         }
300     }
301 }
302 
SetActiveComponent(const std::shared_ptr<ComponentTree> & inputComponent)303 void TreeManager::SetActiveComponent(const std::shared_ptr<ComponentTree>& inputComponent)
304 {
305     // Save one input pointer.
306     if (inputComponent == nullptr) {
307         ERROR_LOG("argument failed inputComponent is nullptr");
308         return;
309     }
310     DEBUG_LOG_STR("Active component: GetNodeId (0x%016llX)", inputComponent->GetNodeId());
311     inputComponent_ = inputComponent;
312     if (elementInfoList_.size() > inputComponent->GetIndex()) {
313         inputElementInfo_ = elementInfoList_[inputComponent->GetIndex()];
314     } else {
315         ERROR_LOG_STR("component index (%d) more than elementInfoList count (%d)", inputComponent->GetIndex(),
316                       elementInfoList_.size());
317     }
318 }
319 
AddPage()320 bool TreeManager::AddPage()
321 {
322     TRACK_LOG_STD();
323     // save new component tree, and change current conmponent tree.
324     UpdateCurrentPage(true);
325 
326     // page tree growth
327     if (newPageNode_ == nullptr) {
328         ERROR_LOG("the new Page Node is null");
329         return false;
330     }
331 
332     uint32_t key = componentTreeList_.size();
333     componentTreeList_[key] = currentComponentNode_;
334     newPageNode_->SetIndex(key);
335     if (!isNewAbility_) {
336         if (currentPageNode_ != nullptr) {
337             newPageNode_->SetParent(currentPageNode_);
338             currentPageNode_->AddChild(newPageNode_);
339         }
340     } else {
341         // ability tree growth
342         key = pageTreeList_.size();
343         pageTreeList_[key] = newPageNode_;
344         currentAbilityNode_->SetIndex(key);
345     }
346     currentPageNode_ = newPageNode_;
347     currentAbilityNode_->AddAllComponentCount(currentPageNode_->GetAllComponentCount());
348 
349     TRACK_LOG_END();
350     return SamePage();
351 }
352 
SamePage()353 bool TreeManager::SamePage()
354 {
355     TRACK_LOG_STD();
356     isUpdateComponentFinished_ = true;
357     newElementInfoList_.clear();
358     if (WuKongLogger::GetInstance()->GetLogLevel() == LOG_LEVEL_TRACK) {
359         DEBUG_LOG_STR("CompoentNode shared  new (%p) count = (%ld) unique (%d)", newComponentNode_.get(),
360                       newComponentNode_.use_count(), newComponentNode_.unique());
361     }
362     newComponentNode_.reset();
363     newPageNode_.reset();
364     newAbilityNode_.reset();
365     TRACK_LOG_END();
366     return true;
367 }
368 
UpdatePage(int layer,uint32_t index)369 bool TreeManager::UpdatePage(int layer, uint32_t index)
370 {
371     TRACK_LOG_STD();
372     DEBUG_LOG_STR("UpdatePage: layer (%d), index (%u)", layer, index);
373     std::shared_ptr<WuKongTree> pageNode = currentPageNode_;
374     if (layer > 0) {
375         if (pageNode->GetChildren().size() <= index) {
376             ERROR_LOG_STR("UpdatePage child index (%d) more than elementInfoList_ GetChildren() size (%u)", index,
377                           pageNode->GetChildren().size());
378             return false;
379         }
380         currentPageNode_ = std::static_pointer_cast<PageTree>(pageNode->GetChildren()[index]);
381     } else {
382         while (layer < 0) {
383             layer++;
384             pageNode = pageNode->GetParent();
385             if (pageNode == nullptr) {
386                 ERROR_LOG_STR("UpdatePage back layer (%d) more than currentPageNode_ parent (%p)", layer,
387                               pageNode.get());
388                 return false;
389             }
390         }
391         currentPageNode_ = std::static_pointer_cast<PageTree>(pageNode);
392     }
393 
394     if (componentTreeList_.find(currentPageNode_->GetIndex()) == componentTreeList_.end()) {
395         ERROR_LOG_STR("currentPageNode_ index (%u) more than componentTreeList_ size (%u)",
396                       currentPageNode_->GetIndex(), componentTreeList_.size());
397         return false;
398     }
399 
400     TRACK_LOG_STR("currentPageNode_->GetIndex(): %d", currentPageNode_->GetIndex());
401     currentComponentNode_ = componentTreeList_[currentPageNode_->GetIndex()];
402 
403     if (!UpdateCurrentPage()) {
404         return false;
405     }
406     TRACK_LOG_END();
407     return SamePage();
408 }
409 
RemovePage()410 bool TreeManager::RemovePage()
411 {
412     TRACK_LOG_STD();
413     uint32_t componentNodeIndex = currentPageNode_->GetIndex();
414     uint32_t componentTreeListCount = componentTreeList_.size();
415     if (componentNodeIndex >= componentTreeListCount) {
416         ERROR_LOG_STR("currentPageNode index (%u) more than componentTreeList_ size (%u)", componentNodeIndex,
417                       componentTreeListCount);
418         return false;
419     }
420     if (WuKongLogger::GetInstance()->GetLogLevel() == LOG_LEVEL_TRACK) {
421         DEBUG_LOG_STR("CompoentNode shared (%p) count = (%ld) unique (%d)",
422                       componentTreeList_[componentNodeIndex].get(), componentTreeList_[componentNodeIndex].use_count(),
423                       componentTreeList_[componentNodeIndex].unique());
424     }
425     auto componentNode = componentTreeList_[componentNodeIndex];
426     if (componentNode == nullptr) {
427         ERROR_LOG("componentNode point is nullptr of currentPageNode");
428         return false;
429     }
430     uint32_t startIndex = componentNode->GetIndex();
431     componentTreeList_[componentNodeIndex].reset();
432     uint32_t endIndex = startIndex + currentPageNode_->count_ - 1;
433     uint32_t elementInfoListCount = elementInfoList_.size();
434     DEBUG_LOG_STR(
435         "currentPageNode StartIndex (%u) EndIndex (%u) componentTreeList_ size (%u) elementInfoList_ size (%u)",
436         startIndex, endIndex, componentTreeListCount, elementInfoListCount);
437     if (startIndex >= elementInfoListCount || endIndex >= elementInfoListCount) {
438         ERROR_LOG_STR("currentPageNode StartIndex (%u) EndIndex (%u) more than elementInfoList_ size (%u)", startIndex,
439                       endIndex, elementInfoListCount);
440         return false;
441     }
442     elementInfoList_.erase(elementInfoList_.begin() + startIndex, elementInfoList_.begin() + endIndex);
443     TRACK_LOG_END();
444     return true;
445 }
446 
UpdateCurrentPage(bool isAdd)447 bool TreeManager::UpdateCurrentPage(bool isAdd)
448 {
449     TRACK_LOG_STD();
450     uint32_t count = elementInfoList_.size();
451     DEBUG_LOG_STR("elementInfoList_: %d", count);
452     for (auto elementInfo : newElementInfoList_) {
453         elementInfoList_.push_back(elementInfo);
454     }
455     if (WuKongLogger::GetInstance()->GetLogLevel() == LOG_LEVEL_TRACK) {
456         DEBUG_LOG_STR("CompoentNode shared  new (%p) count = (%ld) unique (%d)", newComponentNode_.get(),
457                       newComponentNode_.use_count(), newComponentNode_.unique());
458         DEBUG_LOG_STR("CompoentNode shared (%p) count = (%ld) unique (%d)", currentComponentNode_.get(),
459                       currentComponentNode_.use_count(), currentComponentNode_.unique());
460     }
461     // update component tree index
462     newComponentNode_->RecursUpdateNodeIndex(count);
463     if (!isAdd) {
464         newComponentNode_->RecursUpdateInfo(currentComponentNode_);
465     }
466     // set current sreen componentNode to new screen
467     currentComponentNode_ = newComponentNode_;
468     if (WuKongLogger::GetInstance()->GetLogLevel() == LOG_LEVEL_TRACK) {
469         DEBUG_LOG_STR("CompoentNode shared (%p) count = (%ld) unique (%d)", currentComponentNode_.get(),
470                       currentComponentNode_.use_count(), currentComponentNode_.unique());
471         if (currentPageNode_ != nullptr) {
472             DEBUG_LOG_STR("CompoentNode shared (%p) index (%u) count = (%ld) unique (%d)",
473                           componentTreeList_[currentPageNode_->GetIndex()].get(), currentPageNode_->GetIndex(),
474                           componentTreeList_[currentPageNode_->GetIndex()].use_count(),
475                           componentTreeList_[currentPageNode_->GetIndex()].unique());
476         }
477     }
478 
479     if (!isAdd) {
480         componentTreeList_[currentPageNode_->GetIndex()] = currentComponentNode_;
481         currentAbilityNode_->allComponentCount_ -= currentPageNode_->GetAllComponentCount();
482         currentAbilityNode_->allComponentCount_ += newPageNode_->GetAllComponentCount();
483         currentPageNode_->nodeId_ = newPageNode_->nodeId_;
484         currentPageNode_->allComponentCount_ = newPageNode_->allComponentCount_;
485     }
486     TRACK_LOG_END();
487     return true;
488 }
489 }  // namespace WuKong
490 }  // namespace OHOS
491