Game Driver: add GpuStats class to process and dump stats
Bug: 123529932
Test: adb shell dumpsys gpu
Change-Id: I2d524b1eecb00be71d344c07e8e18244a44bbcb8
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
new file mode 100644
index 0000000..43c9492
--- /dev/null
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#undef LOG_TAG
+#define LOG_TAG "GpuStats"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "GpuStats.h"
+
+#include <android-base/stringprintf.h>
+#include <log/log.h>
+#include <utils/Trace.h>
+
+#include <unordered_set>
+
+namespace android {
+
+using base::StringAppendF;
+
+static bool addLoadingCount(GraphicsEnv::Driver driver, bool isDriverLoaded,
+ GpuStatsGlobalAtom* const outGlobalAtom) {
+ switch (driver) {
+ case GraphicsEnv::Driver::GL:
+ case GraphicsEnv::Driver::GL_UPDATED:
+ outGlobalAtom->glLoadingCount++;
+ if (!isDriverLoaded) outGlobalAtom->glLoadingFailureCount++;
+ break;
+ case GraphicsEnv::Driver::VULKAN:
+ case GraphicsEnv::Driver::VULKAN_UPDATED:
+ outGlobalAtom->vkLoadingCount++;
+ if (!isDriverLoaded) outGlobalAtom->vkLoadingFailureCount++;
+ break;
+ default:
+ // Currently we don't support GraphicsEnv::Driver::ANGLE because the
+ // basic driver package info only belongs to system or updated driver.
+ return false;
+ }
+
+ return true;
+}
+
+static void addLoadingTime(GraphicsEnv::Driver driver, int64_t driverLoadingTime,
+ GpuStatsAppAtom* const outAppAtom) {
+ switch (driver) {
+ case GraphicsEnv::Driver::GL:
+ case GraphicsEnv::Driver::GL_UPDATED:
+ outAppAtom->glDriverLoadingTime.emplace_back(driverLoadingTime);
+ break;
+ case GraphicsEnv::Driver::VULKAN:
+ case GraphicsEnv::Driver::VULKAN_UPDATED:
+ outAppAtom->vkDriverLoadingTime.emplace_back(driverLoadingTime);
+ break;
+ default:
+ break;
+ }
+}
+
+void GpuStats::insert(const std::string& driverPackageName, const std::string& driverVersionName,
+ uint64_t driverVersionCode, int64_t driverBuildTime,
+ const std::string& appPackageName, GraphicsEnv::Driver driver,
+ bool isDriverLoaded, int64_t driverLoadingTime) {
+ ATRACE_CALL();
+
+ std::lock_guard<std::mutex> lock(mLock);
+ ALOGV("Received:\n"
+ "\tdriverPackageName[%s]\n"
+ "\tdriverVersionName[%s]\n"
+ "\tdriverVersionCode[%" PRIu64 "]\n"
+ "\tdriverBuildTime[%" PRId64 "]\n"
+ "\tappPackageName[%s]\n"
+ "\tdriver[%d]\n"
+ "\tisDriverLoaded[%d]\n"
+ "\tdriverLoadingTime[%" PRId64 "]",
+ driverPackageName.c_str(), driverVersionName.c_str(), driverVersionCode, driverBuildTime,
+ appPackageName.c_str(), static_cast<int32_t>(driver), isDriverLoaded, driverLoadingTime);
+
+ if (!mGlobalStats.count(driverVersionCode)) {
+ GpuStatsGlobalAtom globalAtom;
+ if (!addLoadingCount(driver, isDriverLoaded, &globalAtom)) {
+ return;
+ }
+ globalAtom.driverPackageName = driverPackageName;
+ globalAtom.driverVersionName = driverVersionName;
+ globalAtom.driverVersionCode = driverVersionCode;
+ globalAtom.driverBuildTime = driverBuildTime;
+ mGlobalStats.insert({driverVersionCode, globalAtom});
+ } else if (!addLoadingCount(driver, isDriverLoaded, &mGlobalStats[driverVersionCode])) {
+ return;
+ }
+
+ if (mAppStats.size() >= MAX_NUM_APP_RECORDS) {
+ ALOGV("GpuStatsAppAtom has reached maximum size. Ignore new stats.");
+ return;
+ }
+
+ const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode);
+ if (!mAppStats.count(appStatsKey)) {
+ GpuStatsAppAtom appAtom;
+ addLoadingTime(driver, driverLoadingTime, &appAtom);
+ appAtom.appPackageName = appPackageName;
+ appAtom.driverVersionCode = driverVersionCode;
+ mAppStats.insert({appStatsKey, appAtom});
+ return;
+ }
+
+ addLoadingTime(driver, driverLoadingTime, &mAppStats[appStatsKey]);
+}
+
+void GpuStats::dump(const Vector<String16>& args, std::string* result) {
+ ATRACE_CALL();
+
+ if (!result) {
+ ALOGE("Dump result shouldn't be nullptr.");
+ return;
+ }
+
+ std::lock_guard<std::mutex> lock(mLock);
+ bool dumpAll = true;
+
+ std::unordered_set<std::string> argsSet;
+ for (size_t i = 0; i < args.size(); i++) {
+ argsSet.insert(String8(args[i]).c_str());
+ }
+
+ const bool dumpGlobal = argsSet.count("--global") != 0;
+ if (dumpGlobal) {
+ dumpGlobalLocked(result);
+ dumpAll = false;
+ }
+
+ const bool dumpApp = argsSet.count("--app") != 0;
+ if (dumpApp) {
+ dumpAppLocked(result);
+ dumpAll = false;
+ }
+
+ if (argsSet.count("--clear")) {
+ bool clearAll = true;
+
+ if (dumpGlobal) {
+ mGlobalStats.clear();
+ clearAll = false;
+ }
+
+ if (dumpApp) {
+ mAppStats.clear();
+ clearAll = false;
+ }
+
+ if (clearAll) {
+ mGlobalStats.clear();
+ mAppStats.clear();
+ }
+
+ dumpAll = false;
+ }
+
+ if (dumpAll) {
+ dumpGlobalLocked(result);
+ dumpAppLocked(result);
+ }
+}
+
+void GpuStats::dumpGlobalLocked(std::string* result) {
+ result->append("GpuStats global:\n");
+
+ for (const auto& ele : mGlobalStats) {
+ StringAppendF(result, " driverPackageName = %s\n", ele.second.driverPackageName.c_str());
+ StringAppendF(result, " driverVersionName = %s\n", ele.second.driverVersionName.c_str());
+ StringAppendF(result, " driverVersionCode = %" PRIu64 "\n", ele.second.driverVersionCode);
+ StringAppendF(result, " driverBuildTime = %" PRId64 "\n", ele.second.driverBuildTime);
+ StringAppendF(result, " glLoadingCount = %d\n", ele.second.glLoadingCount);
+ StringAppendF(result, " glLoadingFailureCount = %d\n", ele.second.glLoadingFailureCount);
+ StringAppendF(result, " vkLoadingCount = %d\n", ele.second.vkLoadingCount);
+ StringAppendF(result, " vkLoadingFailureCount = %d\n", ele.second.vkLoadingFailureCount);
+ result->append("\n");
+ }
+}
+
+void GpuStats::dumpAppLocked(std::string* result) {
+ result->append("GpuStats app:\n");
+
+ for (const auto& ele : mAppStats) {
+ StringAppendF(result, " appPackageName = %s\n", ele.second.appPackageName.c_str());
+ StringAppendF(result, " driverVersionCode = %" PRIu64 "\n", ele.second.driverVersionCode);
+
+ result->append(" glDriverLoadingTime:");
+ for (int32_t loadingTime : ele.second.glDriverLoadingTime) {
+ StringAppendF(result, " %d", loadingTime);
+ }
+ result->append("\n");
+
+ result->append(" vkDriverLoadingTime:");
+ for (int32_t loadingTime : ele.second.vkDriverLoadingTime) {
+ StringAppendF(result, " %d", loadingTime);
+ }
+ result->append("\n\n");
+ }
+}
+
+} // namespace android