Merge Android R (rvc-dev-plus-aosp-without-vendor@6692709)
Bug: 166295507
Merged-In: I70ea776b8589ac3a7982c710c5c8b2941d86e55b
Change-Id: Ic1d535e9d2d6f80d95215240dbdb024995b045f8
diff --git a/services/gpuservice/Android.bp b/services/gpuservice/Android.bp
index 7b8e0f8..6eed24a 100644
--- a/services/gpuservice/Android.bp
+++ b/services/gpuservice/Android.bp
@@ -1,20 +1,6 @@
-filegroup {
- name: "gpuservice_sources",
- srcs: [
- "GpuService.cpp",
- "gpustats/GpuStats.cpp"
- ],
-}
-
-filegroup {
- name: "gpuservice_binary_sources",
- srcs: ["main_gpuservice.cpp"],
-}
-
cc_defaults {
name: "gpuservice_defaults",
cflags: [
- "-DLOG_TAG=\"GpuService\"",
"-Wall",
"-Werror",
"-Wformat",
@@ -22,31 +8,38 @@
"-Wunused",
"-Wunreachable-code",
],
- srcs: [
- ":gpuservice_sources",
- ],
- include_dirs: [
- "frameworks/native/vulkan/vkjson",
- "frameworks/native/vulkan/include",
+}
+
+cc_defaults {
+ name: "libgpuservice_defaults",
+ defaults: ["gpuservice_defaults"],
+ cflags: [
+ "-DLOG_TAG=\"GpuService\"",
],
shared_libs: [
"libbase",
"libbinder",
"libcutils",
+ "libgfxstats",
"libgraphicsenv",
"liblog",
"libutils",
- "libvulkan",
+ "libvkjson",
],
static_libs: [
"libserviceutils",
- "libvkjson",
+ ],
+ export_static_lib_headers: [
+ "libserviceutils",
+ ],
+ export_shared_lib_headers: [
+ "libgraphicsenv",
],
}
cc_defaults {
- name: "gpuservice_production_defaults",
- defaults: ["gpuservice_defaults"],
+ name: "libgpuservice_production_defaults",
+ defaults: ["libgpuservice_defaults"],
cflags: [
"-fvisibility=hidden",
"-fwhole-program-vtables", // requires ThinLTO
@@ -56,8 +49,23 @@
},
}
+filegroup {
+ name: "libgpuservice_sources",
+ srcs: [
+ "GpuService.cpp",
+ ],
+}
+
+cc_library_shared {
+ name: "libgpuservice",
+ defaults: ["libgpuservice_production_defaults"],
+ srcs: [
+ ":libgpuservice_sources",
+ ],
+}
+
cc_defaults {
- name: "gpuservice_binary",
+ name: "libgpuservice_binary",
defaults: ["gpuservice_defaults"],
shared_libs: [
"libbinder",
@@ -68,9 +76,17 @@
ldflags: ["-Wl,--export-dynamic"],
}
+filegroup {
+ name: "gpuservice_binary_sources",
+ srcs: ["main_gpuservice.cpp"],
+}
+
cc_binary {
name: "gpuservice",
- defaults: ["gpuservice_binary"],
+ defaults: ["libgpuservice_binary"],
init_rc: ["gpuservice.rc"],
srcs: [":gpuservice_binary_sources"],
+ shared_libs: [
+ "libgpuservice",
+ ],
}
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index c8253e0..81b0a46 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -24,14 +24,13 @@
#include <binder/Parcel.h>
#include <binder/PermissionCache.h>
#include <cutils/properties.h>
+#include <gpustats/GpuStats.h>
#include <private/android_filesystem_config.h>
#include <utils/String8.h>
#include <utils/Trace.h>
#include <vkjson.h>
-#include "gpustats/GpuStats.h"
-
namespace android {
using base::StringAppendF;
@@ -51,27 +50,38 @@
void GpuService::setGpuStats(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,
+ const int32_t vulkanVersion, GpuStatsInfo::Driver driver,
bool isDriverLoaded, int64_t driverLoadingTime) {
- mGpuStats->insert(driverPackageName, driverVersionName, driverVersionCode, driverBuildTime,
- appPackageName, vulkanVersion, driver, isDriverLoaded, driverLoadingTime);
-}
-
-status_t GpuService::getGpuStatsGlobalInfo(std::vector<GpuStatsGlobalInfo>* outStats) const {
- mGpuStats->pullGlobalStats(outStats);
- return OK;
-}
-
-status_t GpuService::getGpuStatsAppInfo(std::vector<GpuStatsAppInfo>* outStats) const {
- mGpuStats->pullAppStats(outStats);
- return OK;
+ mGpuStats->insertDriverStats(driverPackageName, driverVersionName, driverVersionCode,
+ driverBuildTime, appPackageName, vulkanVersion, driver,
+ isDriverLoaded, driverLoadingTime);
}
void GpuService::setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
- const GraphicsEnv::Stats stats, const uint64_t value) {
+ const GpuStatsInfo::Stats stats, const uint64_t value) {
mGpuStats->insertTargetStats(appPackageName, driverVersionCode, stats, value);
}
+void GpuService::setUpdatableDriverPath(const std::string& driverPath) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+
+ // only system_server is allowed to set updatable driver path
+ if (uid != AID_SYSTEM) {
+ ALOGE("Permission Denial: can't set updatable driver path from pid=%d, uid=%d\n", pid, uid);
+ return;
+ }
+
+ std::lock_guard<std::mutex> lock(mLock);
+ mDeveloperDriverPath = driverPath;
+}
+
+std::string GpuService::getUpdatableDriverPath() {
+ std::lock_guard<std::mutex> lock(mLock);
+ return mDeveloperDriverPath;
+}
+
status_t GpuService::shellCommand(int /*in*/, int out, int err, std::vector<String16>& args) {
ATRACE_CALL();
@@ -99,22 +109,27 @@
StringAppendF(&result, "Permission Denial: can't dump gpu from pid=%d, uid=%d\n", pid, uid);
} else {
bool dumpAll = true;
- size_t index = 0;
+ bool dumpDriverInfo = false;
+ bool dumpStats = false;
size_t numArgs = args.size();
if (numArgs) {
- if ((index < numArgs) && (args[index] == String16("--gpustats"))) {
- index++;
- mGpuStats->dump(args, &result);
- dumpAll = false;
+ for (size_t index = 0; index < numArgs; ++index) {
+ if (args[index] == String16("--gpustats")) {
+ dumpStats = true;
+ } else if (args[index] == String16("--gpudriverinfo")) {
+ dumpDriverInfo = true;
+ }
}
+ dumpAll = !(dumpDriverInfo || dumpStats);
}
- if (dumpAll) {
+ if (dumpAll || dumpDriverInfo) {
dumpGameDriverInfo(&result);
result.append("\n");
-
- mGpuStats->dump(Vector<String16>(), &result);
+ }
+ if (dumpAll || dumpStats) {
+ mGpuStats->dump(args, &result);
result.append("\n");
}
}
diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h
index 7d44a35..d1c3aab 100644
--- a/services/gpuservice/GpuService.h
+++ b/services/gpuservice/GpuService.h
@@ -46,12 +46,12 @@
void setGpuStats(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,
+ GpuStatsInfo::Driver driver, bool isDriverLoaded,
int64_t driverLoadingTime) override;
- status_t getGpuStatsGlobalInfo(std::vector<GpuStatsGlobalInfo>* outStats) const override;
- status_t getGpuStatsAppInfo(std::vector<GpuStatsAppInfo>* outStats) const override;
void setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
- const GraphicsEnv::Stats stats, const uint64_t value) override;
+ const GpuStatsInfo::Stats stats, const uint64_t value) override;
+ void setUpdatableDriverPath(const std::string& driverPath) override;
+ std::string getUpdatableDriverPath() override;
/*
* IBinder interface
@@ -75,6 +75,8 @@
* Attributes
*/
std::unique_ptr<GpuStats> mGpuStats;
+ std::mutex mLock;
+ std::string mDeveloperDriverPath;
};
} // namespace android
diff --git a/services/gpuservice/TEST_MAPPING b/services/gpuservice/TEST_MAPPING
new file mode 100644
index 0000000..b345355
--- /dev/null
+++ b/services/gpuservice/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "gpuservice_unittest"
+ }
+ ]
+}
diff --git a/services/gpuservice/gpustats/Android.bp b/services/gpuservice/gpustats/Android.bp
new file mode 100644
index 0000000..f52602a
--- /dev/null
+++ b/services/gpuservice/gpustats/Android.bp
@@ -0,0 +1,29 @@
+cc_library_shared {
+ name: "libgfxstats",
+ srcs: [
+ "GpuStats.cpp",
+ ],
+ shared_libs: [
+ "libcutils",
+ "libgraphicsenv",
+ "liblog",
+ "libprotoutil",
+ "libstatslog",
+ "libstatspull",
+ "libstatssocket",
+ "libutils",
+ ],
+ export_include_dirs: ["include"],
+ export_shared_lib_headers: [
+ "libstatspull",
+ "libstatssocket",
+ ],
+ cppflags: [
+ "-Wall",
+ "-Werror",
+ "-Wformat",
+ "-Wthread-safety",
+ "-Wunused",
+ "-Wunreachable-code",
+ ],
+}
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index 5d27e72..231d068 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -17,30 +17,40 @@
#define LOG_TAG "GpuStats"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include "GpuStats.h"
+#include "gpustats/GpuStats.h"
+#include <android/util/ProtoOutputStream.h>
#include <cutils/properties.h>
#include <log/log.h>
+#include <stats_event.h>
+#include <statslog.h>
#include <utils/Trace.h>
#include <unordered_set>
namespace android {
-static void addLoadingCount(GraphicsEnv::Driver driver, bool isDriverLoaded,
+GpuStats::~GpuStats() {
+ if (mStatsdRegistered) {
+ AStatsManager_clearPullAtomCallback(android::util::GPU_STATS_GLOBAL_INFO);
+ AStatsManager_clearPullAtomCallback(android::util::GPU_STATS_APP_INFO);
+ }
+}
+
+static void addLoadingCount(GpuStatsInfo::Driver driver, bool isDriverLoaded,
GpuStatsGlobalInfo* const outGlobalInfo) {
switch (driver) {
- case GraphicsEnv::Driver::GL:
- case GraphicsEnv::Driver::GL_UPDATED:
+ case GpuStatsInfo::Driver::GL:
+ case GpuStatsInfo::Driver::GL_UPDATED:
outGlobalInfo->glLoadingCount++;
if (!isDriverLoaded) outGlobalInfo->glLoadingFailureCount++;
break;
- case GraphicsEnv::Driver::VULKAN:
- case GraphicsEnv::Driver::VULKAN_UPDATED:
+ case GpuStatsInfo::Driver::VULKAN:
+ case GpuStatsInfo::Driver::VULKAN_UPDATED:
outGlobalInfo->vkLoadingCount++;
if (!isDriverLoaded) outGlobalInfo->vkLoadingFailureCount++;
break;
- case GraphicsEnv::Driver::ANGLE:
+ case GpuStatsInfo::Driver::ANGLE:
outGlobalInfo->angleLoadingCount++;
if (!isDriverLoaded) outGlobalInfo->angleLoadingFailureCount++;
break;
@@ -49,22 +59,22 @@
}
}
-static void addLoadingTime(GraphicsEnv::Driver driver, int64_t driverLoadingTime,
+static void addLoadingTime(GpuStatsInfo::Driver driver, int64_t driverLoadingTime,
GpuStatsAppInfo* const outAppInfo) {
switch (driver) {
- case GraphicsEnv::Driver::GL:
- case GraphicsEnv::Driver::GL_UPDATED:
+ case GpuStatsInfo::Driver::GL:
+ case GpuStatsInfo::Driver::GL_UPDATED:
if (outAppInfo->glDriverLoadingTime.size() < GpuStats::MAX_NUM_LOADING_TIMES) {
outAppInfo->glDriverLoadingTime.emplace_back(driverLoadingTime);
}
break;
- case GraphicsEnv::Driver::VULKAN:
- case GraphicsEnv::Driver::VULKAN_UPDATED:
+ case GpuStatsInfo::Driver::VULKAN:
+ case GpuStatsInfo::Driver::VULKAN_UPDATED:
if (outAppInfo->vkDriverLoadingTime.size() < GpuStats::MAX_NUM_LOADING_TIMES) {
outAppInfo->vkDriverLoadingTime.emplace_back(driverLoadingTime);
}
break;
- case GraphicsEnv::Driver::ANGLE:
+ case GpuStatsInfo::Driver::ANGLE:
if (outAppInfo->angleDriverLoadingTime.size() < GpuStats::MAX_NUM_LOADING_TIMES) {
outAppInfo->angleDriverLoadingTime.emplace_back(driverLoadingTime);
}
@@ -74,13 +84,15 @@
}
}
-void GpuStats::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) {
+void GpuStats::insertDriverStats(const std::string& driverPackageName,
+ const std::string& driverVersionName, uint64_t driverVersionCode,
+ int64_t driverBuildTime, const std::string& appPackageName,
+ const int32_t vulkanVersion, GpuStatsInfo::Driver driver,
+ bool isDriverLoaded, int64_t driverLoadingTime) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mLock);
+ registerStatsdCallbacksIfNeeded();
ALOGV("Received:\n"
"\tdriverPackageName[%s]\n"
"\tdriverVersionName[%s]\n"
@@ -127,21 +139,28 @@
}
void GpuStats::insertTargetStats(const std::string& appPackageName,
- const uint64_t driverVersionCode, const GraphicsEnv::Stats stats,
+ const uint64_t driverVersionCode, const GpuStatsInfo::Stats stats,
const uint64_t /*value*/) {
ATRACE_CALL();
const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode);
std::lock_guard<std::mutex> lock(mLock);
+ registerStatsdCallbacksIfNeeded();
if (!mAppStats.count(appStatsKey)) {
return;
}
switch (stats) {
- case GraphicsEnv::Stats::CPU_VULKAN_IN_USE:
+ case GpuStatsInfo::Stats::CPU_VULKAN_IN_USE:
mAppStats[appStatsKey].cpuVulkanInUse = true;
break;
+ case GpuStatsInfo::Stats::FALSE_PREROTATION:
+ mAppStats[appStatsKey].falsePrerotation = true;
+ break;
+ case GpuStatsInfo::Stats::GLES_1_IN_USE:
+ mAppStats[appStatsKey].gles1InUse = true;
+ break;
default:
break;
}
@@ -157,6 +176,16 @@
mGlobalStats[0].glesVersion = property_get_int32("ro.opengles.version", 0);
}
+void GpuStats::registerStatsdCallbacksIfNeeded() {
+ if (!mStatsdRegistered) {
+ AStatsManager_setPullAtomCallback(android::util::GPU_STATS_GLOBAL_INFO, nullptr,
+ GpuStats::pullAtomCallback, this);
+ AStatsManager_setPullAtomCallback(android::util::GPU_STATS_APP_INFO, nullptr,
+ GpuStats::pullAtomCallback, this);
+ mStatsdRegistered = true;
+ }
+}
+
void GpuStats::dump(const Vector<String16>& args, std::string* result) {
ATRACE_CALL();
@@ -185,6 +214,11 @@
dumpAll = false;
}
+ if (dumpAll) {
+ dumpGlobalLocked(result);
+ dumpAppLocked(result);
+ }
+
if (argsSet.count("--clear")) {
bool clearAll = true;
@@ -202,13 +236,6 @@
mGlobalStats.clear();
mAppStats.clear();
}
-
- dumpAll = false;
- }
-
- if (dumpAll) {
- dumpGlobalLocked(result);
- dumpAppLocked(result);
}
}
@@ -228,34 +255,114 @@
}
}
-void GpuStats::pullGlobalStats(std::vector<GpuStatsGlobalInfo>* outStats) {
- ATRACE_CALL();
+static std::string protoOutputStreamToByteString(android::util::ProtoOutputStream& proto) {
+ if (!proto.size()) return "";
- std::lock_guard<std::mutex> lock(mLock);
- outStats->clear();
- outStats->reserve(mGlobalStats.size());
-
- interceptSystemDriverStatsLocked();
-
- for (const auto& ele : mGlobalStats) {
- outStats->emplace_back(ele.second);
+ std::string byteString;
+ sp<android::util::ProtoReader> reader = proto.data();
+ while (reader->readBuffer() != nullptr) {
+ const size_t toRead = reader->currentToRead();
+ byteString.append((char*)reader->readBuffer(), toRead);
+ reader->move(toRead);
}
- mGlobalStats.clear();
+ if (byteString.size() != proto.size()) return "";
+
+ return byteString;
}
-void GpuStats::pullAppStats(std::vector<GpuStatsAppInfo>* outStats) {
+static std::string int64VectorToProtoByteString(const std::vector<int64_t>& value) {
+ if (value.empty()) return "";
+
+ android::util::ProtoOutputStream proto;
+ for (const auto& ele : value) {
+ proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED |
+ 1 /* field id */,
+ (long long)ele);
+ }
+
+ return protoOutputStreamToByteString(proto);
+}
+
+AStatsManager_PullAtomCallbackReturn GpuStats::pullAppInfoAtom(AStatsEventList* data) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mLock);
- outStats->clear();
- outStats->reserve(mAppStats.size());
- for (const auto& ele : mAppStats) {
- outStats->emplace_back(ele.second);
+ if (data) {
+ for (const auto& ele : mAppStats) {
+ AStatsEvent* event = AStatsEventList_addStatsEvent(data);
+ AStatsEvent_setAtomId(event, android::util::GPU_STATS_APP_INFO);
+ AStatsEvent_writeString(event, ele.second.appPackageName.c_str());
+ AStatsEvent_writeInt64(event, ele.second.driverVersionCode);
+
+ std::string bytes = int64VectorToProtoByteString(ele.second.glDriverLoadingTime);
+ AStatsEvent_writeByteArray(event, (const uint8_t*)bytes.c_str(), bytes.length());
+
+ bytes = int64VectorToProtoByteString(ele.second.vkDriverLoadingTime);
+ AStatsEvent_writeByteArray(event, (const uint8_t*)bytes.c_str(), bytes.length());
+
+ bytes = int64VectorToProtoByteString(ele.second.angleDriverLoadingTime);
+ AStatsEvent_writeByteArray(event, (const uint8_t*)bytes.c_str(), bytes.length());
+
+ AStatsEvent_writeBool(event, ele.second.cpuVulkanInUse);
+ AStatsEvent_writeBool(event, ele.second.falsePrerotation);
+ AStatsEvent_writeBool(event, ele.second.gles1InUse);
+ AStatsEvent_build(event);
+ }
}
mAppStats.clear();
+
+ return AStatsManager_PULL_SUCCESS;
+}
+
+AStatsManager_PullAtomCallbackReturn GpuStats::pullGlobalInfoAtom(AStatsEventList* data) {
+ ATRACE_CALL();
+
+ std::lock_guard<std::mutex> lock(mLock);
+ // flush cpuVulkanVersion and glesVersion to builtin driver stats
+ interceptSystemDriverStatsLocked();
+
+ if (data) {
+ for (const auto& ele : mGlobalStats) {
+ AStatsEvent* event = AStatsEventList_addStatsEvent(data);
+ AStatsEvent_setAtomId(event, android::util::GPU_STATS_GLOBAL_INFO);
+ AStatsEvent_writeString(event, ele.second.driverPackageName.c_str());
+ AStatsEvent_writeString(event, ele.second.driverVersionName.c_str());
+ AStatsEvent_writeInt64(event, ele.second.driverVersionCode);
+ AStatsEvent_writeInt64(event, ele.second.driverBuildTime);
+ AStatsEvent_writeInt64(event, ele.second.glLoadingCount);
+ AStatsEvent_writeInt64(event, ele.second.glLoadingFailureCount);
+ AStatsEvent_writeInt64(event, ele.second.vkLoadingCount);
+ AStatsEvent_writeInt64(event, ele.second.vkLoadingFailureCount);
+ AStatsEvent_writeInt32(event, ele.second.vulkanVersion);
+ AStatsEvent_writeInt32(event, ele.second.cpuVulkanVersion);
+ AStatsEvent_writeInt32(event, ele.second.glesVersion);
+ AStatsEvent_writeInt64(event, ele.second.angleLoadingCount);
+ AStatsEvent_writeInt64(event, ele.second.angleLoadingFailureCount);
+ AStatsEvent_build(event);
+ }
+ }
+
+ mGlobalStats.clear();
+
+ return AStatsManager_PULL_SUCCESS;
+}
+
+AStatsManager_PullAtomCallbackReturn GpuStats::pullAtomCallback(int32_t atomTag,
+ AStatsEventList* data,
+ void* cookie) {
+ ATRACE_CALL();
+
+ GpuStats* pGpuStats = reinterpret_cast<GpuStats*>(cookie);
+ if (atomTag == android::util::GPU_STATS_GLOBAL_INFO) {
+ return pGpuStats->pullGlobalInfoAtom(data);
+ } else if (atomTag == android::util::GPU_STATS_APP_INFO) {
+ return pGpuStats->pullAppInfoAtom(data);
+ }
+
+ return AStatsManager_PULL_SKIP;
}
} // namespace android
diff --git a/services/gpuservice/gpustats/GpuStats.h b/services/gpuservice/gpustats/GpuStats.h
deleted file mode 100644
index 378f7f4..0000000
--- a/services/gpuservice/gpustats/GpuStats.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <mutex>
-#include <unordered_map>
-#include <vector>
-
-#include <graphicsenv/GpuStatsInfo.h>
-#include <graphicsenv/GraphicsEnv.h>
-#include <utils/String16.h>
-#include <utils/Vector.h>
-
-namespace android {
-
-class GpuStats {
-public:
- GpuStats() = default;
- ~GpuStats() = default;
-
- // Insert new gpu stats into global stats and app stats.
- void 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);
- // Insert target stats into app stats or potentially global stats as well.
- void insertTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
- const GraphicsEnv::Stats stats, const uint64_t value);
- // dumpsys interface
- void dump(const Vector<String16>& args, std::string* result);
- // Pull gpu global stats
- void pullGlobalStats(std::vector<GpuStatsGlobalInfo>* outStats);
- // Pull gpu app stats
- void pullAppStats(std::vector<GpuStatsAppInfo>* outStats);
-
- // This limits the worst case number of loading times tracked.
- static const size_t MAX_NUM_LOADING_TIMES = 50;
-
-private:
- // Dump global stats
- void dumpGlobalLocked(std::string* result);
- // Dump app stats
- void dumpAppLocked(std::string* result);
- // Append cpuVulkanVersion and glesVersion to system driver stats
- void interceptSystemDriverStatsLocked();
-
- // Below limits the memory usage of GpuStats to be less than 10KB. This is
- // the preferred number for statsd while maintaining nice data quality.
- static const size_t MAX_NUM_APP_RECORDS = 100;
- // GpuStats access should be guarded by mLock.
- std::mutex mLock;
- // Key is driver version code.
- std::unordered_map<uint64_t, GpuStatsGlobalInfo> mGlobalStats;
- // Key is <app package name>+<driver version code>.
- std::unordered_map<std::string, GpuStatsAppInfo> mAppStats;
-};
-
-} // namespace android
diff --git a/services/gpuservice/gpustats/include/gpustats/GpuStats.h b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
new file mode 100644
index 0000000..55f0da1
--- /dev/null
+++ b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <graphicsenv/GpuStatsInfo.h>
+#include <graphicsenv/GraphicsEnv.h>
+#include <stats_pull_atom_callback.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+#include <mutex>
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+
+class GpuStats {
+public:
+ ~GpuStats();
+
+ // Insert new gpu driver stats into global stats and app stats.
+ void insertDriverStats(const std::string& driverPackageName,
+ const std::string& driverVersionName, uint64_t driverVersionCode,
+ int64_t driverBuildTime, const std::string& appPackageName,
+ const int32_t vulkanVersion, GpuStatsInfo::Driver driver,
+ bool isDriverLoaded, int64_t driverLoadingTime);
+ // Insert target stats into app stats or potentially global stats as well.
+ void insertTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+ const GpuStatsInfo::Stats stats, const uint64_t value);
+ // dumpsys interface
+ void dump(const Vector<String16>& args, std::string* result);
+
+ // This limits the worst case number of loading times tracked.
+ static const size_t MAX_NUM_LOADING_TIMES = 50;
+
+private:
+ // Friend class for testing.
+ friend class TestableGpuStats;
+
+ // Native atom puller callback registered in statsd.
+ static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atomTag,
+ AStatsEventList* data,
+ void* cookie);
+ // Pull global into into global atom.
+ AStatsManager_PullAtomCallbackReturn pullGlobalInfoAtom(AStatsEventList* data);
+ // Pull app into into app atom.
+ AStatsManager_PullAtomCallbackReturn pullAppInfoAtom(AStatsEventList* data);
+ // Dump global stats
+ void dumpGlobalLocked(std::string* result);
+ // Dump app stats
+ void dumpAppLocked(std::string* result);
+ // Append cpuVulkanVersion and glesVersion to system driver stats
+ void interceptSystemDriverStatsLocked();
+ // Registers statsd callbacks if they have not already been registered
+ void registerStatsdCallbacksIfNeeded();
+
+ // Below limits the memory usage of GpuStats to be less than 10KB. This is
+ // the preferred number for statsd while maintaining nice data quality.
+ static const size_t MAX_NUM_APP_RECORDS = 100;
+ // GpuStats access should be guarded by mLock.
+ std::mutex mLock;
+ // True if statsd callbacks have been registered.
+ bool mStatsdRegistered = false;
+ // Key is driver version code.
+ std::unordered_map<uint64_t, GpuStatsGlobalInfo> mGlobalStats;
+ // Key is <app package name>+<driver version code>.
+ std::unordered_map<std::string, GpuStatsAppInfo> mAppStats;
+};
+
+} // namespace android
diff --git a/services/gpuservice/tests/unittests/Android.bp b/services/gpuservice/tests/unittests/Android.bp
new file mode 100644
index 0000000..538506d
--- /dev/null
+++ b/services/gpuservice/tests/unittests/Android.bp
@@ -0,0 +1,36 @@
+// Copyright 2020 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.
+
+cc_test {
+ name: "gpuservice_unittest",
+ test_suites: ["device-tests"],
+ sanitize: {
+ address: true,
+ },
+ srcs: [
+ "GpuStatsTest.cpp",
+ ],
+ shared_libs: [
+ "libcutils",
+ "libgfxstats",
+ "libgraphicsenv",
+ "liblog",
+ "libstatslog",
+ "libstatspull",
+ "libutils",
+ ],
+ static_libs: [
+ "libgmock",
+ ],
+}
diff --git a/services/gpuservice/tests/unittests/AndroidTest.xml b/services/gpuservice/tests/unittests/AndroidTest.xml
new file mode 100644
index 0000000..66f51c7
--- /dev/null
+++ b/services/gpuservice/tests/unittests/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2020 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.
+-->
+<configuration description="Config for gpuservice_unittest">
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="gpuservice_unittest->/data/local/tmp/gpuservice_unittest" />
+ </target_preparer>
+ <option name="test-suite-tag" value="apct" />
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="gpuservice_unittest" />
+ </test>
+</configuration>
diff --git a/services/gpuservice/tests/unittests/GpuStatsTest.cpp b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
new file mode 100644
index 0000000..37ebeae
--- /dev/null
+++ b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2020 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 "gpuservice_unittest"
+
+#include <cutils/properties.h>
+#include <gmock/gmock.h>
+#include <gpustats/GpuStats.h>
+#include <gtest/gtest.h>
+#include <stats_pull_atom_callback.h>
+#include <statslog.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+#include "TestableGpuStats.h"
+
+namespace android {
+namespace {
+
+using testing::HasSubstr;
+
+// clang-format off
+#define BUILTIN_DRIVER_PKG_NAME "system"
+#define BUILTIN_DRIVER_VER_NAME "0"
+#define BUILTIN_DRIVER_VER_CODE 0
+#define BUILTIN_DRIVER_BUILD_TIME 123
+#define UPDATED_DRIVER_PKG_NAME "updated"
+#define UPDATED_DRIVER_VER_NAME "1"
+#define UPDATED_DRIVER_VER_CODE 1
+#define UPDATED_DRIVER_BUILD_TIME 234
+#define VULKAN_VERSION 345
+#define APP_PKG_NAME_1 "testapp1"
+#define APP_PKG_NAME_2 "testapp2"
+#define DRIVER_LOADING_TIME_1 678
+#define DRIVER_LOADING_TIME_2 789
+#define DRIVER_LOADING_TIME_3 891
+
+enum InputCommand : int32_t {
+ DUMP_ALL = 0,
+ DUMP_GLOBAL = 1,
+ DUMP_APP = 2,
+ DUMP_ALL_THEN_CLEAR = 3,
+ DUMP_GLOBAL_THEN_CLEAR = 4,
+ DUMP_APP_THEN_CLEAR = 5,
+};
+// clang-format on
+
+class GpuStatsTest : public testing::Test {
+public:
+ GpuStatsTest() {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+ }
+
+ ~GpuStatsTest() {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+ }
+
+ std::string inputCommand(InputCommand cmd);
+
+ void SetUp() override {
+ mCpuVulkanVersion = property_get_int32("ro.cpuvulkan.version", 0);
+ mGlesVersion = property_get_int32("ro.opengles.version", 0);
+ }
+
+ std::unique_ptr<GpuStats> mGpuStats = std::make_unique<GpuStats>();
+ int32_t mCpuVulkanVersion = 0;
+ int32_t mGlesVersion = 0;
+};
+
+std::string GpuStatsTest::inputCommand(InputCommand cmd) {
+ std::string result;
+ Vector<String16> args;
+
+ switch (cmd) {
+ case InputCommand::DUMP_ALL:
+ break;
+ case InputCommand::DUMP_GLOBAL:
+ args.push_back(String16("--global"));
+ break;
+ case InputCommand::DUMP_APP:
+ args.push_back(String16("--app"));
+ break;
+ case InputCommand::DUMP_ALL_THEN_CLEAR:
+ args.push_back(String16("--clear"));
+ break;
+ case InputCommand::DUMP_GLOBAL_THEN_CLEAR:
+ args.push_back(String16("--global"));
+ args.push_back(String16("--clear"));
+ break;
+ case InputCommand::DUMP_APP_THEN_CLEAR:
+ args.push_back(String16("--app"));
+ args.push_back(String16("--clear"));
+ break;
+ }
+
+ mGpuStats->dump(args, &result);
+ return result;
+}
+
+TEST_F(GpuStatsTest, statsEmptyByDefault) {
+ ASSERT_TRUE(inputCommand(InputCommand::DUMP_ALL).empty());
+}
+
+TEST_F(GpuStatsTest, canInsertBuiltinDriverStats) {
+ mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+ BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
+ VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+ DRIVER_LOADING_TIME_1);
+
+ std::string expectedResult = "driverPackageName = " + std::string(BUILTIN_DRIVER_PKG_NAME);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr(expectedResult));
+ expectedResult = "driverVersionName = " + std::string(BUILTIN_DRIVER_VER_NAME);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr(expectedResult));
+ expectedResult = "driverVersionCode = " + std::to_string(BUILTIN_DRIVER_VER_CODE);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr(expectedResult));
+ expectedResult = "driverBuildTime = " + std::to_string(BUILTIN_DRIVER_BUILD_TIME);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr(expectedResult));
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr("glLoadingCount = 1"));
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr("glLoadingFailureCount = 0"));
+ expectedResult = "appPackageName = " + std::string(APP_PKG_NAME_1);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult));
+ expectedResult = "driverVersionCode = " + std::to_string(BUILTIN_DRIVER_VER_CODE);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult));
+ expectedResult = "glDriverLoadingTime: " + std::to_string(DRIVER_LOADING_TIME_1);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult));
+}
+
+TEST_F(GpuStatsTest, canInsertUpdatedDriverStats) {
+ mGpuStats->insertDriverStats(UPDATED_DRIVER_PKG_NAME, UPDATED_DRIVER_VER_NAME,
+ UPDATED_DRIVER_VER_CODE, UPDATED_DRIVER_BUILD_TIME, APP_PKG_NAME_2,
+ VULKAN_VERSION, GpuStatsInfo::Driver::VULKAN_UPDATED, false,
+ DRIVER_LOADING_TIME_2);
+
+ std::string expectedResult = "driverPackageName = " + std::string(UPDATED_DRIVER_PKG_NAME);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr(expectedResult));
+ expectedResult = "driverVersionName = " + std::string(UPDATED_DRIVER_VER_NAME);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr(expectedResult));
+ expectedResult = "driverVersionCode = " + std::to_string(UPDATED_DRIVER_VER_CODE);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr(expectedResult));
+ expectedResult = "driverBuildTime = " + std::to_string(UPDATED_DRIVER_BUILD_TIME);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr(expectedResult));
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr("vkLoadingCount = 1"));
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr("vkLoadingFailureCount = 1"));
+ expectedResult = "appPackageName = " + std::string(APP_PKG_NAME_2);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult));
+ expectedResult = "driverVersionCode = " + std::to_string(UPDATED_DRIVER_VER_CODE);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult));
+ expectedResult = "vkDriverLoadingTime: " + std::to_string(DRIVER_LOADING_TIME_2);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult));
+}
+
+TEST_F(GpuStatsTest, canInsertAngleDriverStats) {
+ mGpuStats->insertDriverStats(UPDATED_DRIVER_PKG_NAME, UPDATED_DRIVER_VER_NAME,
+ UPDATED_DRIVER_VER_CODE, UPDATED_DRIVER_BUILD_TIME, APP_PKG_NAME_2,
+ VULKAN_VERSION, GpuStatsInfo::Driver::ANGLE, true,
+ DRIVER_LOADING_TIME_3);
+
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr("angleLoadingCount = 1"));
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr("angleLoadingFailureCount = 0"));
+ std::string expectedResult = "angleDriverLoadingTime: " + std::to_string(DRIVER_LOADING_TIME_3);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult));
+}
+
+TEST_F(GpuStatsTest, canDump3dApiVersion) {
+ mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+ BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
+ VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+ DRIVER_LOADING_TIME_1);
+
+ std::string expectedResult = "vulkanVersion = " + std::to_string(VULKAN_VERSION);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr(expectedResult));
+ expectedResult = "cpuVulkanVersion = " + std::to_string(mCpuVulkanVersion);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr(expectedResult));
+ expectedResult = "glesVersion = " + std::to_string(mGlesVersion);
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_GLOBAL), HasSubstr(expectedResult));
+}
+
+TEST_F(GpuStatsTest, canNotInsertTargetStatsBeforeProperSetup) {
+ mGpuStats->insertTargetStats(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+ GpuStatsInfo::Stats::CPU_VULKAN_IN_USE, 0);
+ mGpuStats->insertTargetStats(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+ GpuStatsInfo::Stats::FALSE_PREROTATION, 0);
+ mGpuStats->insertTargetStats(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+ GpuStatsInfo::Stats::GLES_1_IN_USE, 0);
+
+ EXPECT_TRUE(inputCommand(InputCommand::DUMP_APP).empty());
+}
+
+TEST_F(GpuStatsTest, canInsertTargetStatsAfterProperSetup) {
+ mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+ BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
+ VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+ DRIVER_LOADING_TIME_1);
+ mGpuStats->insertTargetStats(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+ GpuStatsInfo::Stats::CPU_VULKAN_IN_USE, 0);
+ mGpuStats->insertTargetStats(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+ GpuStatsInfo::Stats::FALSE_PREROTATION, 0);
+ mGpuStats->insertTargetStats(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+ GpuStatsInfo::Stats::GLES_1_IN_USE, 0);
+
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("cpuVulkanInUse = 1"));
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("falsePrerotation = 1"));
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("gles1InUse = 1"));
+}
+
+TEST_F(GpuStatsTest, canDumpAllBeforeClearAll) {
+ mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+ BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
+ VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+ DRIVER_LOADING_TIME_1);
+
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_ALL_THEN_CLEAR).empty());
+ EXPECT_TRUE(inputCommand(InputCommand::DUMP_ALL).empty());
+}
+
+TEST_F(GpuStatsTest, canDumpGlobalBeforeClearGlobal) {
+ mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+ BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
+ VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+ DRIVER_LOADING_TIME_1);
+
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_GLOBAL_THEN_CLEAR).empty());
+ EXPECT_TRUE(inputCommand(InputCommand::DUMP_GLOBAL).empty());
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_APP).empty());
+}
+
+TEST_F(GpuStatsTest, canDumpAppBeforeClearApp) {
+ mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+ BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
+ VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+ DRIVER_LOADING_TIME_1);
+
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_APP_THEN_CLEAR).empty());
+ EXPECT_TRUE(inputCommand(InputCommand::DUMP_APP).empty());
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_GLOBAL).empty());
+}
+
+TEST_F(GpuStatsTest, skipPullInvalidAtom) {
+ TestableGpuStats testableGpuStats(mGpuStats.get());
+ mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+ BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
+ VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+ DRIVER_LOADING_TIME_1);
+
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_GLOBAL).empty());
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_APP).empty());
+
+ EXPECT_TRUE(testableGpuStats.makePullAtomCallback(-1) == AStatsManager_PULL_SKIP);
+
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_GLOBAL).empty());
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_APP).empty());
+}
+
+TEST_F(GpuStatsTest, canPullGlobalAtom) {
+ TestableGpuStats testableGpuStats(mGpuStats.get());
+ mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+ BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
+ VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+ DRIVER_LOADING_TIME_1);
+
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_GLOBAL).empty());
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_APP).empty());
+
+ EXPECT_TRUE(testableGpuStats.makePullAtomCallback(android::util::GPU_STATS_GLOBAL_INFO) ==
+ AStatsManager_PULL_SUCCESS);
+
+ EXPECT_TRUE(inputCommand(InputCommand::DUMP_GLOBAL).empty());
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_APP).empty());
+}
+
+TEST_F(GpuStatsTest, canPullAppAtom) {
+ TestableGpuStats testableGpuStats(mGpuStats.get());
+ mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+ BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
+ VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+ DRIVER_LOADING_TIME_1);
+
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_GLOBAL).empty());
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_APP).empty());
+
+ EXPECT_TRUE(testableGpuStats.makePullAtomCallback(android::util::GPU_STATS_APP_INFO) ==
+ AStatsManager_PULL_SUCCESS);
+
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_GLOBAL).empty());
+ EXPECT_TRUE(inputCommand(InputCommand::DUMP_APP).empty());
+}
+
+} // namespace
+} // namespace android
diff --git a/services/gpuservice/tests/unittests/TestableGpuStats.h b/services/gpuservice/tests/unittests/TestableGpuStats.h
new file mode 100644
index 0000000..4ea564c
--- /dev/null
+++ b/services/gpuservice/tests/unittests/TestableGpuStats.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#pragma once
+
+#include <gpustats/GpuStats.h>
+#include <stdint.h>
+
+namespace android {
+
+class TestableGpuStats {
+public:
+ explicit TestableGpuStats(GpuStats *gpuStats) : mGpuStats(gpuStats) {}
+
+ AStatsManager_PullAtomCallbackReturn makePullAtomCallback(int32_t atomTag) {
+ return mGpuStats->pullAtomCallback(atomTag, nullptr, mGpuStats);
+ }
+
+private:
+ GpuStats *mGpuStats;
+};
+
+} // namespace android