1 /*
2 * Copyright (c) 2022-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 "property/rs_property_trace.h"
17
18 #include <climits>
19 #include <cstdarg>
20 #include <fstream>
21 #include <regex>
22 #include <securec.h>
23 #include <sys/time.h>
24 #include "directory_ex.h"
25
26 #include "rs_trace.h"
27 #include "platform/common/rs_log.h"
28
29 namespace OHOS {
30 namespace Rosen {
31 const std::string ANIMATION_LOG_PATH = "/etc/rosen/";
32 const std::string CONFIG_FILE_NAME = "property.config";
33 const std::string COLON_SEPARATOR = ":";
34 const std::string COMMA_SEPARATOR = ",";
35 const std::string SEMICOLON_SEPARATOR = ";";
36 const std::string NODE_ID_TAG = "ID";
37 const std::string NODE_NAME_TAG = "NODE_NAME:";
38 const std::string ALL_NEED_TAG = "all";
39 static constexpr int MIN_INFO_SIZE = 2;
40 RSPropertyTrace RSPropertyTrace::instance_;
41
PropertiesDisplayByTrace(const NodeId & id,const std::shared_ptr<RSObjAbsGeometry> & boundsGeometry)42 void RSPropertyTrace::PropertiesDisplayByTrace(const NodeId& id,
43 const std::shared_ptr<RSObjAbsGeometry>& boundsGeometry)
44 {
45 if (IsNeedPropertyTrace(id)) {
46 auto rectI = boundsGeometry->GetAbsRect();
47 AddTraceFlag(std::to_string(id) + " Geometry Rect: " + rectI.ToString());
48 }
49 }
50
TracePropertiesByNodeName(const NodeId & id,const std::string & nodeName,const RSProperties & properties)51 void RSPropertyTrace::TracePropertiesByNodeName(const NodeId& id, const std::string& nodeName,
52 const RSProperties& properties)
53 {
54 if (!IsNeedPropertyTrace(nodeName)) {
55 return;
56 }
57 std::string content = "NodeId:[" + std::to_string(id) + "], NodeName:[" + nodeName + "]" +
58 " Geometry Rect: " + (properties.GetBoundsGeometry())->GetAbsRect().ToString() +
59 " Bounds Rect: " + properties.GetBoundsRect().ToString() +
60 " Frame Rect: " + properties.GetFrameRect().ToString() +
61 " Alpha: " + std::to_string(properties.GetAlpha()) +
62 " Visible: " + std::to_string(properties.GetVisible());
63 AddTraceFlag(content);
64 }
65
RefreshNodeTraceInfo()66 void RSPropertyTrace::RefreshNodeTraceInfo()
67 {
68 if (IsNeedRefreshConfig()) {
69 InitNodeAndPropertyInfo();
70 }
71 }
72
AddTraceFlag(const std::string & str)73 void RSPropertyTrace::AddTraceFlag(const std::string& str)
74 {
75 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, str.c_str());
76 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
77 }
78
SplitStringBySeparator(const std::string & str,const std::string & separator)79 std::vector<std::string> SplitStringBySeparator(const std::string& str,
80 const std::string& separator)
81 {
82 std::regex re(separator);
83 std::sregex_token_iterator pos(str.begin(), str.end(), re, -1);
84 std::sregex_token_iterator endPos;
85 std::vector<std::string> result;
86 while (pos != endPos) {
87 result.emplace_back(*pos++);
88 }
89 return result;
90 }
91
InitNodeAndPropertyInfo()92 void RSPropertyTrace::InitNodeAndPropertyInfo()
93 {
94 std::string configFilePath = ANIMATION_LOG_PATH + CONFIG_FILE_NAME;
95 std::string newpath;
96 if (!PathToRealPath(configFilePath, newpath)) {
97 ROSEN_LOGE("Render node trace config file is nullptr!");
98 return;
99 }
100 std::ifstream configFile(newpath);
101 if (!configFile.is_open()) {
102 ROSEN_LOGE("Open render node trace config file failed!");
103 return;
104 }
105
106 std::string info;
107 while (std::getline(configFile, info)) {
108 if (DealNodeNameConfig(info)) {
109 continue;
110 }
111 std::vector<std::string> infos = SplitStringBySeparator(info, SEMICOLON_SEPARATOR);
112 if (infos.empty()) {
113 continue;
114 }
115 DealConfigInputInfo(infos.front());
116 }
117 configFile.close();
118 }
119
DealConfigInputInfo(const std::string & info)120 void RSPropertyTrace::DealConfigInputInfo(const std::string& info)
121 {
122 std::vector<std::string> splitResult = SplitStringBySeparator(info, COLON_SEPARATOR);
123 if (splitResult.size() != MIN_INFO_SIZE) {
124 ROSEN_LOGE("Render node trace config file size error!");
125 return;
126 }
127
128 std::string tag = splitResult.front();
129 if (tag == NODE_ID_TAG) {
130 std::vector<std::string> nodeIds =
131 SplitStringBySeparator(splitResult.back(), COMMA_SEPARATOR);
132 for (std::string nodeId : nodeIds) {
133 if (nodeId == ALL_NEED_TAG) {
134 needWriteAllNode_ = true;
135 return;
136 }
137 auto id = atoll(nodeId.c_str());
138 nodeIdSet_.insert(id);
139 }
140 }
141 }
142
DealNodeNameConfig(const std::string & info)143 bool RSPropertyTrace::DealNodeNameConfig(const std::string& info)
144 {
145 if (info.compare(0, NODE_NAME_TAG.size(), NODE_NAME_TAG) != 0) {
146 return false;
147 }
148
149 if (info == NODE_NAME_TAG) {
150 needTraceAllNode_ = true;
151 return true;
152 }
153
154 needTraceAllNode_ = false;
155 std::vector<std::string> nodeNames = SplitStringBySeparator(info.substr(NODE_NAME_TAG.size()), COMMA_SEPARATOR);
156 for (std::string nodeName : nodeNames) {
157 nodeNameSet_.insert(nodeName);
158 }
159 return true;
160 }
161
ClearNodeAndPropertyInfo()162 void RSPropertyTrace::ClearNodeAndPropertyInfo()
163 {
164 nodeIdSet_.clear();
165 nodeNameSet_.clear();
166 }
167
IsNeedRefreshConfig()168 bool RSPropertyTrace::IsNeedRefreshConfig()
169 {
170 struct stat configFileStatus = {};
171 std::string configFilePath = ANIMATION_LOG_PATH + CONFIG_FILE_NAME;
172 if (stat(configFilePath.c_str(), &configFileStatus)) {
173 return false;
174 }
175
176 std::string curent(ctime(&configFileStatus.st_mtime));
177 if (curent != propertyFileLastModifyTime) {
178 propertyFileLastModifyTime = curent;
179 return true;
180 }
181 return false;
182 }
183
IsNeedPropertyTrace(const NodeId & id)184 bool RSPropertyTrace::IsNeedPropertyTrace(const NodeId& id)
185 {
186 auto itrn = nodeIdSet_.find(id);
187 if (itrn == nodeIdSet_.end() && !needWriteAllNode_) {
188 return false;
189 }
190 return true;
191 }
192
IsNeedPropertyTrace(const std::string & nodeName)193 bool RSPropertyTrace::IsNeedPropertyTrace(const std::string& nodeName)
194 {
195 if (nodeName == "") {
196 return false;
197 }
198 return needTraceAllNode_ || (nodeNameSet_.find(nodeName) != nodeNameSet_.end());
199 }
200 } // namespace Rosen
201 } // namespace OHOS
202