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
28 namespace OHOS {
29 namespace Rosen {
30 const std::string ANIMATION_LOG_PATH = "/etc/rosen/";
31 const std::string CONFIG_FILE_NAME = "property.config";
32 const std::string COLON_SEPARATOR = ":";
33 const std::string COMMA_SEPARATOR = ",";
34 const std::string SEMICOLON_SEPARATOR = ";";
35 const std::string NODE_ID_TAG = "ID";
36 const std::string PROPERTY_ID_TAG = "PROPERTY";
37 const std::string ALL_NEED_TAG = "all";
38 const std::string CORNER_PROPERTY_TAG = "corner";
39 const std::string ALPHA_PROPERTY_TAG = "alpha";
40 const std::string SHADOW_PROPERTY_TAG = "shadow";
41 static constexpr int MIN_INFO_SIZE = 2;
42 RSPropertyTrace RSPropertyTrace::instance_;
43
PropertiesDisplayByTrace(const NodeId & id,const RSProperties & properties)44 void RSPropertyTrace::PropertiesDisplayByTrace(const NodeId& id, const RSProperties& properties)
45 {
46 if (IsNeedPropertyTrace(id)) {
47 auto rectI = (properties.GetBoundsGeometry())->GetAbsRect();
48 std::string str = std::to_string(id) + " Geometry Rect: " + rectI.ToString();
49 for (auto property : propertySet_) {
50 if (property == CORNER_PROPERTY_TAG) {
51 auto corner = properties.GetCornerRadius();
52 str = str + " Corner:(" + std::to_string(corner.x_) +
53 "," + std::to_string(corner.y_) +
54 "," + std::to_string(corner.z_) +
55 "," + std::to_string(corner.w_) + ")";
56 } else if (property == ALPHA_PROPERTY_TAG) {
57 auto alpha = properties.GetAlpha();
58 str = str + " Alpha:" + std::to_string(alpha);
59 } else if (property == SHADOW_PROPERTY_TAG) {
60 auto shadowColor = properties.GetShadowColor();
61 auto shadowAlpha = properties.GetShadowAlpha();
62 auto shadowOffsetX = properties.GetShadowOffsetX();
63 auto shadowOffsetY = properties.GetShadowOffsetY();
64 auto shadowRadius = properties.GetShadowRadius();
65 auto shadowElevation = properties.GetShadowElevation();
66 str = str + " Shadow:{color:(" + std::to_string(shadowColor.GetRed()) +
67 "," + std::to_string(shadowColor.GetGreen()) +
68 "," + std::to_string(shadowColor.GetBlue()) +
69 "),offset:(" + std::to_string(shadowOffsetX) +
70 "," + std::to_string(shadowOffsetY) +
71 "),radius:" + std::to_string(shadowRadius) +
72 ",elevation:" + std::to_string(shadowElevation) +
73 ",alpha:" + std::to_string(shadowAlpha) + "}";
74 }
75 }
76 AddTraceFlag(str);
77 }
78 }
79
RefreshNodeTraceInfo()80 void RSPropertyTrace::RefreshNodeTraceInfo()
81 {
82 if (IsNeedRefreshConfig()) {
83 ClearNodeAndPropertyInfo();
84 InitNodeAndPropertyInfo();
85 }
86 }
87
AddTraceFlag(const std::string & str)88 void RSPropertyTrace::AddTraceFlag(const std::string& str)
89 {
90 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, str.c_str());
91 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
92 }
93
SplitStringBySeparator(const std::string & str,const std::string & separator)94 std::vector<std::string> SplitStringBySeparator(const std::string& str,
95 const std::string& separator)
96 {
97 std::regex re(separator);
98 std::sregex_token_iterator pos(str.begin(), str.end(), re, -1);
99 std::sregex_token_iterator endPos;
100 std::vector<std::string> result;
101 while (pos != endPos) {
102 result.emplace_back(*pos++);
103 }
104 return result;
105 }
106
InitNodeAndPropertyInfo()107 void RSPropertyTrace::InitNodeAndPropertyInfo()
108 {
109 std::string configFilePath = ANIMATION_LOG_PATH + CONFIG_FILE_NAME;
110 std::string newpath;
111 if (!PathToRealPath(configFilePath, newpath)) {
112 ROSEN_LOGE("Render node trace config file is nullptr!");
113 return;
114 }
115 std::ifstream configFile(newpath);
116 if (!configFile.is_open()) {
117 ROSEN_LOGE("Open render node trace config file failed!");
118 return;
119 }
120
121 std::string info;
122 while (std::getline(configFile, info)) {
123 std::vector<std::string> infos = SplitStringBySeparator(info, SEMICOLON_SEPARATOR);
124 if (infos.empty()) {
125 continue;
126 }
127 DealConfigInputInfo(infos.front());
128 }
129 configFile.close();
130 }
131
DealConfigInputInfo(const std::string & info)132 void RSPropertyTrace::DealConfigInputInfo(const std::string& info)
133 {
134 std::vector<std::string> splitResult = SplitStringBySeparator(info, COLON_SEPARATOR);
135 if (splitResult.size() != MIN_INFO_SIZE) {
136 ROSEN_LOGE("Render node trace config file size error!");
137 return;
138 }
139
140 std::string tag = splitResult.front();
141 if (tag == NODE_ID_TAG) {
142 std::vector<std::string> nodeIds =
143 SplitStringBySeparator(splitResult.back(), COMMA_SEPARATOR);
144 for (std::string nodeId : nodeIds) {
145 if (nodeId == ALL_NEED_TAG) {
146 needWriteAllNode_ = true;
147 return;
148 }
149 auto id = atoll(nodeId.c_str());
150 nodeIdSet_.insert(id);
151 }
152 } else if (tag == PROPERTY_ID_TAG) {
153 std::vector<std::string> propertys =
154 SplitStringBySeparator(splitResult.back(), COMMA_SEPARATOR);
155 for (std::string property : propertys) {
156 propertySet_.insert(property);
157 }
158 }
159 }
160
ClearNodeAndPropertyInfo()161 void RSPropertyTrace::ClearNodeAndPropertyInfo()
162 {
163 nodeIdSet_.clear();
164 propertySet_.clear();
165 }
166
IsNeedRefreshConfig()167 bool RSPropertyTrace::IsNeedRefreshConfig()
168 {
169 struct stat configFileStatus = {};
170 std::string configFilePath = ANIMATION_LOG_PATH + CONFIG_FILE_NAME;
171 if (stat(configFilePath.c_str(), &configFileStatus)) {
172 return false;
173 }
174
175 std::string curent(ctime(&configFileStatus.st_mtime));
176 if (curent != propertyFileLastModifyTime) {
177 propertyFileLastModifyTime = curent;
178 return true;
179 }
180 return false;
181 }
182
IsNeedPropertyTrace(const NodeId & id)183 bool RSPropertyTrace::IsNeedPropertyTrace(const NodeId& id)
184 {
185 auto itrn = nodeIdSet_.find(id);
186 if (itrn == nodeIdSet_.end() && !needWriteAllNode_) {
187 return false;
188 }
189 return true;
190 }
191 } // namespace Rosen
192 } // namespace OHOS
193