1 /*
2 * Copyright (c) 2025 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 #ifndef LOG_TAG
17 #define LOG_TAG "HpaeDfxTree"
18 #endif
19 #include "hpae_dfx_tree.h"
20 #include "audio_engine_log.h"
21 namespace OHOS {
22 namespace AudioStandard {
23 namespace HPAE {
24
FindDfxNode(DfxTreeNode * currentNode,const uint32_t nodeId)25 DfxTreeNode *HpaeDfxTree::FindDfxNode(DfxTreeNode *currentNode, const uint32_t nodeId)
26 {
27 if (!currentNode) {
28 return nullptr;
29 }
30 std::queue<DfxTreeNode *> q;
31 q.push(currentNode);
32 while (!q.empty()) {
33 DfxTreeNode *node = q.front();
34 q.pop();
35 if (node->nodeInfo_.nodeId == nodeId) {
36 return node;
37 }
38 for (auto &child : node->children_) {
39 q.push(child);
40 }
41 }
42 return nullptr;
43 }
44
FindDfxParent(DfxTreeNode * target)45 DfxTreeNode *HpaeDfxTree::FindDfxParent(DfxTreeNode *target)
46 {
47 if (!root_ || target == root_) {
48 return nullptr;
49 }
50 std::queue<DfxTreeNode *> q;
51 q.push(root_);
52 while (!q.empty()) {
53 DfxTreeNode *node = q.front();
54 q.pop();
55 for (auto &child : node->children_) {
56 if (child->nodeInfo_.nodeId == target->nodeInfo_.nodeId) {
57 return node;
58 }
59 q.push(child);
60 }
61 }
62 return nullptr;
63 }
64
Insert(const uint32_t parentNodeId,const HpaeDfxNodeInfo & info)65 bool HpaeDfxTree::Insert(const uint32_t parentNodeId, const HpaeDfxNodeInfo &info)
66 {
67 if (!root_) {
68 AUDIO_INFO_LOG("Insert Root is null");
69 root_ = new DfxTreeNode(info);
70 return true;
71 }
72 DfxTreeNode *parent = FindDfxNode(root_, parentNodeId);
73 if (!parent) {
74 AUDIO_INFO_LOG("Insert can not find correct parent");
75 return false;
76 }
77 auto it = find_if(parent->children_.begin(), parent->children_.end(),
78 [&info](DfxTreeNode *node) -> bool { return node->nodeInfo_.nodeId == info.nodeId; });
79 if (it == parent->children_.end()) {
80 parent->children_.push_back(new DfxTreeNode(info));
81 }
82 return true;
83 }
84
Remove(const uint32_t nodeId)85 bool HpaeDfxTree::Remove(const uint32_t nodeId)
86 {
87 if (!root_) {
88 AUDIO_INFO_LOG("Remove Root is null");
89 return false;
90 }
91 DfxTreeNode *nodeToRemove = FindDfxNode(root_, nodeId);
92 if (!nodeToRemove) {
93 return false;
94 }
95
96 if (nodeToRemove == root_) {
97 delete root_;
98 root_ = nullptr;
99 return true;
100 }
101
102 DfxTreeNode *parent = FindDfxParent(nodeToRemove);
103 if (!parent) {
104 return false;
105 }
106 // Remove from parent's children
107 auto &children = parent->children_;
108 auto it = find(children.begin(), children.end(), nodeToRemove);
109 if (it != children.end()) {
110 children.erase(it);
111 delete nodeToRemove;
112 return true;
113 }
114 return false;
115 }
116
LevelOrderTraversal()117 std::vector<std::vector<HpaeDfxNodeInfo>> HpaeDfxTree::LevelOrderTraversal()
118 {
119 std::vector<std::vector<HpaeDfxNodeInfo>> result;
120 if (!root_) {
121 return result;
122 }
123 std::queue<DfxTreeNode *> q;
124 q.push(root_);
125 while (!q.empty()) {
126 size_t levelSize = q.size();
127 std::vector<HpaeDfxNodeInfo> curLevelResult;
128 for (size_t i = 0; i < levelSize; ++i) {
129 DfxTreeNode *node = q.front();
130 q.pop();
131 curLevelResult.push_back(node->nodeInfo_);
132 for (auto &child : node->children_) {
133 q.push(child);
134 }
135 }
136 result.push_back(curLevelResult);
137 }
138 return result;
139 }
140
PrintNodeInfo(std::string & outStr,HpaeDfxNodeInfo & nodeInfo)141 void HpaeDfxTree::PrintNodeInfo(std::string &outStr, HpaeDfxNodeInfo &nodeInfo)
142 {
143 outStr = outStr + nodeInfo.nodeName + ": " + "sessionId[" + std::to_string(nodeInfo.sessionId) + "],";
144 outStr = outStr + "nodeId[" + std::to_string(nodeInfo.nodeId) + "],";
145 outStr = outStr + "rate[" + std::to_string(nodeInfo.samplingRate) + "],";
146 outStr = outStr + "ch[" + std::to_string(nodeInfo.channels) + "],";
147 outStr = outStr + "bw[" + std::to_string(nodeInfo.format) + "],";
148 outStr = outStr + "len[" + std::to_string(nodeInfo.frameLen) + "],";
149 outStr = outStr + "scene[" + std::to_string(nodeInfo.sceneType) + "] \n";
150 }
151
PrintSubTree(DfxTreeNode * node,const std::string & prefix,bool isLastChild,std::string & outStr)152 void HpaeDfxTree::PrintSubTree(DfxTreeNode *node, const std::string &prefix, bool isLastChild, std::string &outStr)
153 {
154 if (!node) {
155 return;
156 }
157
158 outStr = outStr + prefix;
159 outStr = outStr + (isLastChild ? "|___ " : "|--- ");
160 PrintNodeInfo(outStr, node->nodeInfo_);
161 std::string newPrefix = prefix + (isLastChild ? " " : "| ");
162 for (size_t i = 0; i < node->children_.size(); ++i) {
163 bool childIsLast = (i == node->children_.size() - 1);
164 PrintSubTree(node->children_[i], newPrefix, childIsLast, outStr);
165 }
166 }
167
PrintTree(std::string & outStr)168 void HpaeDfxTree::PrintTree(std::string &outStr)
169 {
170 if (!root_) {
171 return;
172 }
173 PrintNodeInfo(outStr, root_->nodeInfo_);
174 for (size_t i = 0; i < root_->children_.size(); ++i) {
175 bool isLast = (i == root_->children_.size() - 1);
176 PrintSubTree(root_->children_[i], "", isLast, outStr);
177 }
178 }
179
UpdateNodeInfo(uint32_t nodeId,const HpaeDfxNodeInfo & nodeInfo)180 void HpaeDfxTree::UpdateNodeInfo(uint32_t nodeId, const HpaeDfxNodeInfo &nodeInfo)
181 {
182 if (root_ == nullptr) {
183 AUDIO_WARNING_LOG("Hidumper dfx tree is empty!");
184 return;
185 }
186 DfxTreeNode *target = FindDfxNode(root_, nodeId);
187 if (target == nullptr) {
188 AUDIO_WARNING_LOG("Cannot find Node Id: %{public}d", nodeId);
189 return;
190 }
191 target->nodeInfo_ = nodeInfo;
192 }
193
194 } // namespace HPAE
195 } // namespace AudioStandard
196 } // namespace OHOS