GpuStats: migrate to new statsd native puller api (part 3)

This change migrates the app atom puller over to the new api.

Bug: 148421389
Test: atest gpuservice_unittest
Test: statsd_testdrive 10054
Test: statsd_testdrive 10055
Change-Id: I629ea35e7205f469d168c5c7a58904d74b2e6308
diff --git a/services/gpuservice/gpustats/Android.bp b/services/gpuservice/gpustats/Android.bp
index e366477..f52602a 100644
--- a/services/gpuservice/gpustats/Android.bp
+++ b/services/gpuservice/gpustats/Android.bp
@@ -7,6 +7,7 @@
         "libcutils",
         "libgraphicsenv",
         "liblog",
+        "libprotoutil",
         "libstatslog",
         "libstatspull",
         "libstatssocket",
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index 430c350..d094532 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -17,8 +17,9 @@
 #define LOG_TAG "GpuStats"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <gpustats/GpuStats.h>
+#include "gpustats/GpuStats.h"
 
+#include <android/util/ProtoOutputStream.h>
 #include <cutils/properties.h>
 #include <log/log.h>
 #include <stats_event.h>
@@ -32,10 +33,13 @@
 GpuStats::GpuStats() {
     AStatsManager_registerPullAtomCallback(android::util::GPU_STATS_GLOBAL_INFO,
                                            GpuStats::pullAtomCallback, nullptr, this);
+    AStatsManager_registerPullAtomCallback(android::util::GPU_STATS_APP_INFO,
+                                           GpuStats::pullAtomCallback, nullptr, this);
 }
 
 GpuStats::~GpuStats() {
     AStatsManager_unregisterPullAtomCallback(android::util::GPU_STATS_GLOBAL_INFO);
+    AStatsManager_unregisterPullAtomCallback(android::util::GPU_STATS_APP_INFO);
 }
 
 static void addLoadingCount(GpuStatsInfo::Driver driver, bool isDriverLoaded,
@@ -244,6 +248,68 @@
     }
 }
 
+static std::string protoOutputStreamToByteString(android::util::ProtoOutputStream& proto) {
+    if (!proto.size()) return "";
+
+    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);
+    }
+
+    if (byteString.size() != proto.size()) return "";
+
+    return byteString;
+}
+
+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);
+
+    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();
 
@@ -285,6 +351,8 @@
     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;
diff --git a/services/gpuservice/gpustats/include/gpustats/GpuStats.h b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
index 749c9b7..8ca4e4e 100644
--- a/services/gpuservice/gpustats/include/gpustats/GpuStats.h
+++ b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
@@ -58,6 +58,8 @@
                                                                  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
diff --git a/services/gpuservice/tests/unittests/GpuStatsTest.cpp b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
index 7e39f9e..37ebeae 100644
--- a/services/gpuservice/tests/unittests/GpuStatsTest.cpp
+++ b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
@@ -286,5 +286,22 @@
     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