Add engine name to GpuStatsAppInfo

The engine name from VkApplicationInfo is useful for collection metrics
on Vulkan usage. Add it to the collected metrics in GpuStatsAppInfo.

Bug: 330118952
Test: adb shell dumpsys gpu
Test: atest GpuStatsTest
Change-Id: If4096b8a96ed77ddb1d2fd9f48c2b8825b3d0280
diff --git a/libs/graphicsenv/GpuStatsInfo.cpp b/libs/graphicsenv/GpuStatsInfo.cpp
index 7b74214..33cebe3 100644
--- a/libs/graphicsenv/GpuStatsInfo.cpp
+++ b/libs/graphicsenv/GpuStatsInfo.cpp
@@ -96,6 +96,7 @@
     if ((status = parcel->writeUint64(vulkanDeviceFeaturesEnabled)) != OK) return status;
     if ((status = parcel->writeInt32Vector(vulkanInstanceExtensions)) != OK) return status;
     if ((status = parcel->writeInt32Vector(vulkanDeviceExtensions)) != OK) return status;
+    if ((status = parcel->writeUtf8VectorAsUtf16Vector(vulkanEngineNames)) != OK) return status;
 
     return OK;
 }
@@ -118,6 +119,7 @@
     if ((status = parcel->readUint64(&vulkanDeviceFeaturesEnabled)) != OK) return status;
     if ((status = parcel->readInt32Vector(&vulkanInstanceExtensions)) != OK) return status;
     if ((status = parcel->readInt32Vector(&vulkanDeviceExtensions)) != OK) return status;
+    if ((status = parcel->readUtf8VectorFromUtf16Vector(&vulkanEngineNames)) != OK) return status;
 
     return OK;
 }
@@ -161,6 +163,11 @@
         StringAppendF(&result, " 0x%x", extension);
     }
     result.append("\n");
+    result.append("vulkanEngineNames:");
+    for (const std::string& engineName : vulkanEngineNames) {
+        StringAppendF(&result, " %s,", engineName.c_str());
+    }
+    result.append("\n");
     return result;
 }
 
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 50c05f4..52383ac 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -445,6 +445,21 @@
                         extensionHashes, numStats);
 }
 
+void GraphicsEnv::addVulkanEngineName(const char* engineName) {
+    ATRACE_CALL();
+    if (engineName == nullptr) {
+        return;
+    }
+    std::lock_guard<std::mutex> lock(mStatsLock);
+    if (!readyToSendGpuStatsLocked()) return;
+
+    const sp<IGpuService> gpuService = getGpuService();
+    if (gpuService) {
+        gpuService->addVulkanEngineName(mGpuStats.appPackageName, mGpuStats.driverVersionCode,
+                                        engineName);
+    }
+}
+
 bool GraphicsEnv::readyToSendGpuStatsLocked() {
     // Only send stats for processes having at least one activity launched and that process doesn't
     // skip the GraphicsEnvironment setup.
diff --git a/libs/graphicsenv/IGpuService.cpp b/libs/graphicsenv/IGpuService.cpp
index 5dc195c..42e7c37 100644
--- a/libs/graphicsenv/IGpuService.cpp
+++ b/libs/graphicsenv/IGpuService.cpp
@@ -77,6 +77,19 @@
                            IBinder::FLAG_ONEWAY);
     }
 
+    void addVulkanEngineName(const std::string& appPackageName, const uint64_t driverVersionCode,
+                             const char* engineName) override {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGpuService::getInterfaceDescriptor());
+
+        data.writeUtf8AsUtf16(appPackageName);
+        data.writeUint64(driverVersionCode);
+        data.writeCString(engineName);
+
+        remote()->transact(BnGpuService::ADD_VULKAN_ENGINE_NAME, data, &reply,
+                           IBinder::FLAG_ONEWAY);
+    }
+
     void setUpdatableDriverPath(const std::string& driverPath) override {
         Parcel data, reply;
         data.writeInterfaceToken(IGpuService::getInterfaceDescriptor());
@@ -197,6 +210,21 @@
 
             return OK;
         }
+        case ADD_VULKAN_ENGINE_NAME: {
+            CHECK_INTERFACE(IGpuService, data, reply);
+
+            std::string appPackageName;
+            if ((status = data.readUtf8FromUtf16(&appPackageName)) != OK) return status;
+
+            uint64_t driverVersionCode;
+            if ((status = data.readUint64(&driverVersionCode)) != OK) return status;
+
+            const char* engineName;
+            if ((engineName = data.readCString()) == nullptr) return BAD_VALUE;
+
+            addVulkanEngineName(appPackageName, driverVersionCode, engineName);
+            return OK;
+        }
         case SET_UPDATABLE_DRIVER_PATH: {
             CHECK_INTERFACE(IGpuService, data, reply);
 
diff --git a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
index 9ebaf16..23f583b 100644
--- a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
+++ b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
@@ -60,6 +60,10 @@
 public:
     // This limits the worst case number of extensions to be tracked.
     static const uint32_t MAX_NUM_EXTENSIONS = 100;
+    // Max number of vulkan engine names for a single GpuStatsAppInfo
+    static const uint32_t MAX_VULKAN_ENGINE_NAMES = 16;
+    // Max length of a vulkan engine name string
+    static const size_t MAX_VULKAN_ENGINE_NAME_LENGTH = 50;
 
     GpuStatsAppInfo() = default;
     GpuStatsAppInfo(const GpuStatsAppInfo&) = default;
@@ -84,6 +88,7 @@
     uint64_t vulkanDeviceFeaturesEnabled = 0;
     std::vector<int32_t> vulkanInstanceExtensions = {};
     std::vector<int32_t> vulkanDeviceExtensions = {};
+    std::vector<std::string> vulkanEngineNames = {};
 
     std::chrono::time_point<std::chrono::system_clock> lastAccessTime;
 };
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 6cce3f6..b0ab0b9 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -89,6 +89,8 @@
     // Set which device extensions are enabled for the app.
     void setVulkanDeviceExtensions(uint32_t enabledExtensionCount,
                                    const char* const* ppEnabledExtensionNames);
+    // Add the engine name passed in VkApplicationInfo during CreateInstance
+    void addVulkanEngineName(const char* engineName);
 
     /*
      * Api for Vk/GL layer injection.  Presently, drivers enable certain
diff --git a/libs/graphicsenv/include/graphicsenv/IGpuService.h b/libs/graphicsenv/include/graphicsenv/IGpuService.h
index 45f05d6..a0d6e37 100644
--- a/libs/graphicsenv/include/graphicsenv/IGpuService.h
+++ b/libs/graphicsenv/include/graphicsenv/IGpuService.h
@@ -46,6 +46,8 @@
                                      const uint64_t driverVersionCode,
                                      const GpuStatsInfo::Stats stats, const uint64_t* values,
                                      const uint32_t valueCount) = 0;
+    virtual void addVulkanEngineName(const std::string& appPackageName,
+                                     const uint64_t driverVersionCode, const char* engineName) = 0;
 
     // setter and getter for updatable driver path.
     virtual void setUpdatableDriverPath(const std::string& driverPath) = 0;
@@ -64,6 +66,7 @@
         GET_UPDATABLE_DRIVER_PATH,
         TOGGLE_ANGLE_AS_SYSTEM_DRIVER,
         SET_TARGET_STATS_ARRAY,
+        ADD_VULKAN_ENGINE_NAME,
         // Always append new enum to the end.
     };
 
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index a481c62..fadb1fd 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -100,6 +100,12 @@
     mGpuStats->insertTargetStatsArray(appPackageName, driverVersionCode, stats, values, valueCount);
 }
 
+void GpuService::addVulkanEngineName(const std::string& appPackageName,
+                                     const uint64_t driverVersionCode,
+                                     const char* engineName) {
+    mGpuStats->addVulkanEngineName(appPackageName, driverVersionCode, engineName);
+}
+
 void GpuService::toggleAngleAsSystemDriver(bool enabled) {
     IPCThreadState* ipc = IPCThreadState::self();
     const int pid = ipc->getCallingPid();
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index 11b636d..6d758bc 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -181,6 +181,33 @@
     return insertTargetStatsArray(appPackageName, driverVersionCode, stats, &value, 1);
 }
 
+void GpuStats::addVulkanEngineName(const std::string& appPackageName,
+                                   const uint64_t driverVersionCode,
+                                   const char* engineNameCStr) {
+    ATRACE_CALL();
+
+    const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode);
+    const size_t engineNameLen = std::min(strlen(engineNameCStr),
+                                          GpuStatsAppInfo::MAX_VULKAN_ENGINE_NAME_LENGTH);
+    const std::string engineName{engineNameCStr, engineNameLen};
+
+    std::lock_guard<std::mutex> lock(mLock);
+    registerStatsdCallbacksIfNeeded();
+
+    const auto foundApp = mAppStats.find(appStatsKey);
+    if (foundApp == mAppStats.end()) {
+        return;
+    }
+
+    // Storing in std::set<> is not efficient for serialization tasks. Use
+    // vector instead and filter out dups
+    std::vector<std::string>& engineNames = foundApp->second.vulkanEngineNames;
+    if (engineNames.size() < GpuStatsAppInfo::MAX_VULKAN_ENGINE_NAMES
+        && std::find(engineNames.cbegin(), engineNames.cend(), engineName) == engineNames.cend()) {
+        engineNames.push_back(engineName);
+    }
+}
+
 void GpuStats::insertTargetStatsArray(const std::string& appPackageName,
                                  const uint64_t driverVersionCode, const GpuStatsInfo::Stats stats,
                                  const uint64_t* values, const uint32_t valueCount) {
@@ -389,6 +416,11 @@
             std::string angleDriverBytes = int64VectorToProtoByteString(
                 ele.second.angleDriverLoadingTime);
 
+            std::vector<const char*> engineNames;
+            for (const std::string &engineName : ele.second.vulkanEngineNames) {
+                engineNames.push_back(engineName.c_str());
+            }
+
             android::util::addAStatsEvent(
                     data,
                     android::util::GPU_STATS_APP_INFO,
@@ -410,7 +442,8 @@
                     ele.second.vulkanApiVersion,
                     ele.second.vulkanDeviceFeaturesEnabled,
                     ele.second.vulkanInstanceExtensions,
-                    ele.second.vulkanDeviceExtensions);
+                    ele.second.vulkanDeviceExtensions,
+                    engineNames);
         }
     }
 
diff --git a/services/gpuservice/gpustats/include/gpustats/GpuStats.h b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
index 22c64db..961f011 100644
--- a/services/gpuservice/gpustats/include/gpustats/GpuStats.h
+++ b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
@@ -44,6 +44,9 @@
     void insertTargetStatsArray(const std::string& appPackageName,
                            const uint64_t driverVersionCode, const GpuStatsInfo::Stats stats,
                            const uint64_t* values, const uint32_t valueCount);
+    // Add the engine name passed in VkApplicationInfo during CreateInstance
+    void addVulkanEngineName(const std::string& appPackageName,
+                             const uint64_t driverVersionCode, const char* engineName);
     // dumpsys interface
     void dump(const Vector<String16>& args, std::string* result);
 
diff --git a/services/gpuservice/include/gpuservice/GpuService.h b/services/gpuservice/include/gpuservice/GpuService.h
index 54f8f66..3072885 100644
--- a/services/gpuservice/include/gpuservice/GpuService.h
+++ b/services/gpuservice/include/gpuservice/GpuService.h
@@ -64,6 +64,8 @@
     void setUpdatableDriverPath(const std::string& driverPath) override;
     std::string getUpdatableDriverPath() override;
     void toggleAngleAsSystemDriver(bool enabled) override;
+    void addVulkanEngineName(const std::string& appPackageName, const uint64_t driverVersionCode,
+                             const char *engineName) override;
 
     /*
      * IBinder interface
diff --git a/services/gpuservice/tests/unittests/GpuStatsTest.cpp b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
index 4ce533f..b367457 100644
--- a/services/gpuservice/tests/unittests/GpuStatsTest.cpp
+++ b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
@@ -46,6 +46,8 @@
 #define UPDATED_DRIVER_VER_CODE   1
 #define UPDATED_DRIVER_BUILD_TIME 234
 #define VULKAN_VERSION            345
+#define VULKAN_ENGINE_NAME_1      "testVulkanEngine1"
+#define VULKAN_ENGINE_NAME_2      "testVulkanEngine2"
 #define APP_PKG_NAME_1            "testapp1"
 #define APP_PKG_NAME_2            "testapp2"
 #define DRIVER_LOADING_TIME_1     678
@@ -243,6 +245,8 @@
     mGpuStats->insertTargetStats(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
                                  GpuStatsInfo::Stats::VULKAN_DEVICE_EXTENSION,
                                  VULKAN_DEVICE_EXTENSION_1);
+    mGpuStats->addVulkanEngineName(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+                             VULKAN_ENGINE_NAME_1);
 
     EXPECT_TRUE(inputCommand(InputCommand::DUMP_APP).empty());
 }
@@ -282,6 +286,8 @@
     mGpuStats->insertTargetStats(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
                                  GpuStatsInfo::Stats::VULKAN_DEVICE_EXTENSION,
                                  VULKAN_DEVICE_EXTENSION_2);
+    mGpuStats->addVulkanEngineName(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+                             VULKAN_ENGINE_NAME_1);
 
     EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("cpuVulkanInUse = 1"));
     EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("falsePrerotation = 1"));
@@ -302,6 +308,64 @@
     expectedResult.str("");
     expectedResult << "vulkanDeviceExtensions: 0x" << std::hex << VULKAN_DEVICE_EXTENSION_1
                     << " 0x" << std::hex << VULKAN_DEVICE_EXTENSION_2;
+    expectedResult.str("");
+    expectedResult << "vulkanEngineNames: " << VULKAN_ENGINE_NAME_1 << ",";
+
+    EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult.str()));
+}
+
+// Verify the vulkanEngineNames list behaves like a set and dedupes additions
+TEST_F(GpuStatsTest, vulkanEngineNamesBehavesLikeSet) {
+    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);
+    for (int i = 0; i < 4; i++) {
+        mGpuStats->addVulkanEngineName(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+                                       VULKAN_ENGINE_NAME_1);
+    }
+
+    std::stringstream wrongResult, expectedResult;
+    wrongResult << "vulkanEngineNames: " << VULKAN_ENGINE_NAME_1 << ", " <<
+                   VULKAN_ENGINE_NAME_1;
+    expectedResult << "vulkanEngineNames: " << VULKAN_ENGINE_NAME_1;
+
+    EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), Not(HasSubstr(wrongResult.str())));
+    EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult.str()));
+}
+
+TEST_F(GpuStatsTest, vulkanEngineNamesCheckEmptyEngineNameAlone) {
+    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->addVulkanEngineName(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+                                   "");
+
+    std::stringstream expectedResult;
+    expectedResult << "vulkanEngineNames: ,";
+
+    EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult.str()));
+}
+
+TEST_F(GpuStatsTest, vulkanEngineNamesCheckEmptyEngineNameWithOthers) {
+    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->addVulkanEngineName(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+                                   VULKAN_ENGINE_NAME_1);
+    mGpuStats->addVulkanEngineName(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+                                   "");
+    mGpuStats->addVulkanEngineName(APP_PKG_NAME_1, BUILTIN_DRIVER_VER_CODE,
+                                   VULKAN_ENGINE_NAME_2);
+
+    std::stringstream expectedResult;
+    expectedResult << "vulkanEngineNames: " << VULKAN_ENGINE_NAME_1 << ", "
+                   << ", " <<  VULKAN_ENGINE_NAME_2;
+
     EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult.str()));
 }
 
@@ -350,6 +414,10 @@
         mGpuStats->insertTargetStats(fullPkgName, BUILTIN_DRIVER_VER_CODE,
                                     GpuStatsInfo::Stats::VULKAN_DEVICE_EXTENSION,
                                     VULKAN_DEVICE_EXTENSION_2);
+        mGpuStats->addVulkanEngineName(fullPkgName, BUILTIN_DRIVER_VER_CODE,
+                                 VULKAN_ENGINE_NAME_1);
+        mGpuStats->addVulkanEngineName(fullPkgName, BUILTIN_DRIVER_VER_CODE,
+                                 VULKAN_ENGINE_NAME_2);
 
         EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(fullPkgName.c_str()));
         EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("cpuVulkanInUse = 1"));
@@ -371,6 +439,9 @@
         expectedResult.str("");
         expectedResult << "vulkanDeviceExtensions: 0x" << std::hex << VULKAN_DEVICE_EXTENSION_1
                         << " 0x" << std::hex << VULKAN_DEVICE_EXTENSION_2;
+        expectedResult.str("");
+        expectedResult << "vulkanEngineNames: " << VULKAN_ENGINE_NAME_1 << ", "
+                       << VULKAN_ENGINE_NAME_2 << ",";
         EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(expectedResult.str()));
     }
 
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 81fd118..7ea98f5 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -1372,6 +1372,11 @@
             android::GraphicsEnv::getInstance().setTargetStats(
                 android::GpuStatsInfo::Stats::CREATED_VULKAN_API_VERSION,
                 vulkanApiVersion);
+
+            if (pCreateInfo->pApplicationInfo->pEngineName) {
+                android::GraphicsEnv::getInstance().addVulkanEngineName(
+                    pCreateInfo->pApplicationInfo->pEngineName);
+            }
         }
 
         // Update stats for the extensions requested