1 /*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #undef LOG_TAG
17 #define LOG_TAG "GpuStats"
18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19
20 #include "GpuStats.h"
21
22 #include <cutils/properties.h>
23 #include <log/log.h>
24 #include <utils/Trace.h>
25
26 #include <unordered_set>
27
28 namespace android {
29
addLoadingCount(GraphicsEnv::Driver driver,bool isDriverLoaded,GpuStatsGlobalInfo * const outGlobalInfo)30 static void addLoadingCount(GraphicsEnv::Driver driver, bool isDriverLoaded,
31 GpuStatsGlobalInfo* const outGlobalInfo) {
32 switch (driver) {
33 case GraphicsEnv::Driver::GL:
34 case GraphicsEnv::Driver::GL_UPDATED:
35 outGlobalInfo->glLoadingCount++;
36 if (!isDriverLoaded) outGlobalInfo->glLoadingFailureCount++;
37 break;
38 case GraphicsEnv::Driver::VULKAN:
39 case GraphicsEnv::Driver::VULKAN_UPDATED:
40 outGlobalInfo->vkLoadingCount++;
41 if (!isDriverLoaded) outGlobalInfo->vkLoadingFailureCount++;
42 break;
43 case GraphicsEnv::Driver::ANGLE:
44 outGlobalInfo->angleLoadingCount++;
45 if (!isDriverLoaded) outGlobalInfo->angleLoadingFailureCount++;
46 break;
47 default:
48 break;
49 }
50 }
51
addLoadingTime(GraphicsEnv::Driver driver,int64_t driverLoadingTime,GpuStatsAppInfo * const outAppInfo)52 static void addLoadingTime(GraphicsEnv::Driver driver, int64_t driverLoadingTime,
53 GpuStatsAppInfo* const outAppInfo) {
54 switch (driver) {
55 case GraphicsEnv::Driver::GL:
56 case GraphicsEnv::Driver::GL_UPDATED:
57 if (outAppInfo->glDriverLoadingTime.size() < GpuStats::MAX_NUM_LOADING_TIMES) {
58 outAppInfo->glDriverLoadingTime.emplace_back(driverLoadingTime);
59 }
60 break;
61 case GraphicsEnv::Driver::VULKAN:
62 case GraphicsEnv::Driver::VULKAN_UPDATED:
63 if (outAppInfo->vkDriverLoadingTime.size() < GpuStats::MAX_NUM_LOADING_TIMES) {
64 outAppInfo->vkDriverLoadingTime.emplace_back(driverLoadingTime);
65 }
66 break;
67 case GraphicsEnv::Driver::ANGLE:
68 if (outAppInfo->angleDriverLoadingTime.size() < GpuStats::MAX_NUM_LOADING_TIMES) {
69 outAppInfo->angleDriverLoadingTime.emplace_back(driverLoadingTime);
70 }
71 break;
72 default:
73 break;
74 }
75 }
76
insert(const std::string & driverPackageName,const std::string & driverVersionName,uint64_t driverVersionCode,int64_t driverBuildTime,const std::string & appPackageName,const int32_t vulkanVersion,GraphicsEnv::Driver driver,bool isDriverLoaded,int64_t driverLoadingTime)77 void GpuStats::insert(const std::string& driverPackageName, const std::string& driverVersionName,
78 uint64_t driverVersionCode, int64_t driverBuildTime,
79 const std::string& appPackageName, const int32_t vulkanVersion,
80 GraphicsEnv::Driver driver, bool isDriverLoaded, int64_t driverLoadingTime) {
81 ATRACE_CALL();
82
83 std::lock_guard<std::mutex> lock(mLock);
84 ALOGV("Received:\n"
85 "\tdriverPackageName[%s]\n"
86 "\tdriverVersionName[%s]\n"
87 "\tdriverVersionCode[%" PRIu64 "]\n"
88 "\tdriverBuildTime[%" PRId64 "]\n"
89 "\tappPackageName[%s]\n"
90 "\tvulkanVersion[%d]\n"
91 "\tdriver[%d]\n"
92 "\tisDriverLoaded[%d]\n"
93 "\tdriverLoadingTime[%" PRId64 "]",
94 driverPackageName.c_str(), driverVersionName.c_str(), driverVersionCode, driverBuildTime,
95 appPackageName.c_str(), vulkanVersion, static_cast<int32_t>(driver), isDriverLoaded,
96 driverLoadingTime);
97
98 if (!mGlobalStats.count(driverVersionCode)) {
99 GpuStatsGlobalInfo globalInfo;
100 addLoadingCount(driver, isDriverLoaded, &globalInfo);
101 globalInfo.driverPackageName = driverPackageName;
102 globalInfo.driverVersionName = driverVersionName;
103 globalInfo.driverVersionCode = driverVersionCode;
104 globalInfo.driverBuildTime = driverBuildTime;
105 globalInfo.vulkanVersion = vulkanVersion;
106 mGlobalStats.insert({driverVersionCode, globalInfo});
107 } else {
108 addLoadingCount(driver, isDriverLoaded, &mGlobalStats[driverVersionCode]);
109 }
110
111 const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode);
112 if (!mAppStats.count(appStatsKey)) {
113 if (mAppStats.size() >= MAX_NUM_APP_RECORDS) {
114 ALOGV("GpuStatsAppInfo has reached maximum size. Ignore new stats.");
115 return;
116 }
117
118 GpuStatsAppInfo appInfo;
119 addLoadingTime(driver, driverLoadingTime, &appInfo);
120 appInfo.appPackageName = appPackageName;
121 appInfo.driverVersionCode = driverVersionCode;
122 mAppStats.insert({appStatsKey, appInfo});
123 return;
124 }
125
126 addLoadingTime(driver, driverLoadingTime, &mAppStats[appStatsKey]);
127 }
128
insertTargetStats(const std::string & appPackageName,const uint64_t driverVersionCode,const GraphicsEnv::Stats stats,const uint64_t)129 void GpuStats::insertTargetStats(const std::string& appPackageName,
130 const uint64_t driverVersionCode, const GraphicsEnv::Stats stats,
131 const uint64_t /*value*/) {
132 ATRACE_CALL();
133
134 const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode);
135
136 std::lock_guard<std::mutex> lock(mLock);
137 if (!mAppStats.count(appStatsKey)) {
138 return;
139 }
140
141 switch (stats) {
142 case GraphicsEnv::Stats::CPU_VULKAN_IN_USE:
143 mAppStats[appStatsKey].cpuVulkanInUse = true;
144 break;
145 default:
146 break;
147 }
148 }
149
interceptSystemDriverStatsLocked()150 void GpuStats::interceptSystemDriverStatsLocked() {
151 // Append cpuVulkanVersion and glesVersion to system driver stats
152 if (!mGlobalStats.count(0) || mGlobalStats[0].glesVersion) {
153 return;
154 }
155
156 mGlobalStats[0].cpuVulkanVersion = property_get_int32("ro.cpuvulkan.version", 0);
157 mGlobalStats[0].glesVersion = property_get_int32("ro.opengles.version", 0);
158 }
159
dump(const Vector<String16> & args,std::string * result)160 void GpuStats::dump(const Vector<String16>& args, std::string* result) {
161 ATRACE_CALL();
162
163 if (!result) {
164 ALOGE("Dump result shouldn't be nullptr.");
165 return;
166 }
167
168 std::lock_guard<std::mutex> lock(mLock);
169 bool dumpAll = true;
170
171 std::unordered_set<std::string> argsSet;
172 for (size_t i = 0; i < args.size(); i++) {
173 argsSet.insert(String8(args[i]).c_str());
174 }
175
176 const bool dumpGlobal = argsSet.count("--global") != 0;
177 if (dumpGlobal) {
178 dumpGlobalLocked(result);
179 dumpAll = false;
180 }
181
182 const bool dumpApp = argsSet.count("--app") != 0;
183 if (dumpApp) {
184 dumpAppLocked(result);
185 dumpAll = false;
186 }
187
188 if (argsSet.count("--clear")) {
189 bool clearAll = true;
190
191 if (dumpGlobal) {
192 mGlobalStats.clear();
193 clearAll = false;
194 }
195
196 if (dumpApp) {
197 mAppStats.clear();
198 clearAll = false;
199 }
200
201 if (clearAll) {
202 mGlobalStats.clear();
203 mAppStats.clear();
204 }
205
206 dumpAll = false;
207 }
208
209 if (dumpAll) {
210 dumpGlobalLocked(result);
211 dumpAppLocked(result);
212 }
213 }
214
dumpGlobalLocked(std::string * result)215 void GpuStats::dumpGlobalLocked(std::string* result) {
216 interceptSystemDriverStatsLocked();
217
218 for (const auto& ele : mGlobalStats) {
219 result->append(ele.second.toString());
220 result->append("\n");
221 }
222 }
223
dumpAppLocked(std::string * result)224 void GpuStats::dumpAppLocked(std::string* result) {
225 for (const auto& ele : mAppStats) {
226 result->append(ele.second.toString());
227 result->append("\n");
228 }
229 }
230
pullGlobalStats(std::vector<GpuStatsGlobalInfo> * outStats)231 void GpuStats::pullGlobalStats(std::vector<GpuStatsGlobalInfo>* outStats) {
232 ATRACE_CALL();
233
234 std::lock_guard<std::mutex> lock(mLock);
235 outStats->clear();
236 outStats->reserve(mGlobalStats.size());
237
238 interceptSystemDriverStatsLocked();
239
240 for (const auto& ele : mGlobalStats) {
241 outStats->emplace_back(ele.second);
242 }
243
244 mGlobalStats.clear();
245 }
246
pullAppStats(std::vector<GpuStatsAppInfo> * outStats)247 void GpuStats::pullAppStats(std::vector<GpuStatsAppInfo>* outStats) {
248 ATRACE_CALL();
249
250 std::lock_guard<std::mutex> lock(mLock);
251 outStats->clear();
252 outStats->reserve(mAppStats.size());
253
254 for (const auto& ele : mAppStats) {
255 outStats->emplace_back(ele.second);
256 }
257
258 mAppStats.clear();
259 }
260
261 } // namespace android
262