Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4d6e57f authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Game Driver: add GpuStats class to process and dump stats"

parents d1fe5d34 2d4c1887
Loading
Loading
Loading
Loading
+42 −0
Original line number Original line Diff line number Diff line
/*
 * 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 <string>
#include <vector>

namespace android {

struct GpuStatsGlobalAtom {
    std::string driverPackageName = "";
    std::string driverVersionName = "";
    uint64_t driverVersionCode = 0;
    int64_t driverBuildTime = 0;
    int32_t glLoadingCount = 0;
    int32_t glLoadingFailureCount = 0;
    int32_t vkLoadingCount = 0;
    int32_t vkLoadingFailureCount = 0;
};

struct GpuStatsAppAtom {
    std::string appPackageName = "";
    uint64_t driverVersionCode = 0;
    std::vector<int64_t> glDriverLoadingTime = {};
    std::vector<int64_t> vkDriverLoadingTime = {};
};

} // namespace android
+1 −0
Original line number Original line Diff line number Diff line
@@ -2,6 +2,7 @@ filegroup {
    name: "gpuservice_sources",
    name: "gpuservice_sources",
    srcs: [
    srcs: [
        "GpuService.cpp",
        "GpuService.cpp",
        "gpustats/GpuStats.cpp"
    ],
    ],
}
}


+21 −15
Original line number Original line Diff line number Diff line
@@ -29,6 +29,8 @@


#include <vkjson.h>
#include <vkjson.h>


#include "gpustats/GpuStats.h"

namespace android {
namespace android {


using base::StringAppendF;
using base::StringAppendF;
@@ -42,7 +44,7 @@ const String16 sDump("android.permission.DUMP");


const char* const GpuService::SERVICE_NAME = "gpu";
const char* const GpuService::SERVICE_NAME = "gpu";


GpuService::GpuService() = default;
GpuService::GpuService() : mGpuStats(std::make_unique<GpuStats>()){};


void GpuService::setGpuStats(const std::string& driverPackageName,
void GpuService::setGpuStats(const std::string& driverPackageName,
                             const std::string& driverVersionName, uint64_t driverVersionCode,
                             const std::string& driverVersionName, uint64_t driverVersionCode,
@@ -51,18 +53,8 @@ void GpuService::setGpuStats(const std::string& driverPackageName,
                             int64_t driverLoadingTime) {
                             int64_t driverLoadingTime) {
    ATRACE_CALL();
    ATRACE_CALL();


    std::lock_guard<std::mutex> lock(mStateLock);
    mGpuStats->insert(driverPackageName, driverVersionName, driverVersionCode, driverBuildTime,
    ALOGV("Received:\n"
                      appPackageName, driver, isDriverLoaded, driverLoadingTime);
          "\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);
}
}


status_t GpuService::shellCommand(int /*in*/, int out, int err, std::vector<String16>& args) {
status_t GpuService::shellCommand(int /*in*/, int out, int err, std::vector<String16>& args) {
@@ -81,7 +73,7 @@ status_t GpuService::shellCommand(int /*in*/, int out, int err, std::vector<Stri
    return BAD_VALUE;
    return BAD_VALUE;
}
}


status_t GpuService::doDump(int fd, const Vector<String16>& /*args*/, bool /*asProto*/) {
status_t GpuService::doDump(int fd, const Vector<String16>& args, bool /*asProto*/) {
    std::string result;
    std::string result;


    IPCThreadState* ipc = IPCThreadState::self();
    IPCThreadState* ipc = IPCThreadState::self();
@@ -91,7 +83,21 @@ status_t GpuService::doDump(int fd, const Vector<String16>& /*args*/, bool /*asP
    if ((uid != AID_SHELL) && !PermissionCache::checkPermission(sDump, pid, uid)) {
    if ((uid != AID_SHELL) && !PermissionCache::checkPermission(sDump, pid, uid)) {
        StringAppendF(&result, "Permission Denial: can't dump gpu from pid=%d, uid=%d\n", pid, uid);
        StringAppendF(&result, "Permission Denial: can't dump gpu from pid=%d, uid=%d\n", pid, uid);
    } else {
    } else {
        result.append("Hello world from dumpsys gpu.\n");
        bool dumpAll = true;
        size_t index = 0;
        size_t numArgs = args.size();

        if (numArgs) {
            if ((index < numArgs) && (args[index] == String16("--gpustats"))) {
                index++;
                mGpuStats->dump(args, &result);
                dumpAll = false;
            }
        }

        if (dumpAll) {
            mGpuStats->dump(Vector<String16>(), &result);
        }
    }
    }


    write(fd, result.c_str(), result.size());
    write(fd, result.c_str(), result.size());
+3 −3
Original line number Original line Diff line number Diff line
@@ -27,6 +27,8 @@


namespace android {
namespace android {


class GpuStats;

class GpuService : public BnGpuService, public PriorityDumper {
class GpuService : public BnGpuService, public PriorityDumper {
public:
public:
    static const char* const SERVICE_NAME ANDROID_API;
    static const char* const SERVICE_NAME ANDROID_API;
@@ -66,9 +68,7 @@ private:
    /*
    /*
     * Attributes
     * Attributes
     */
     */

    std::unique_ptr<GpuStats> mGpuStats;
    // GpuStats access must be protected by mStateLock
    std::mutex mStateLock;
};
};


} // namespace android
} // namespace android
+213 −0
Original line number Original line Diff line number Diff line
/*
 * 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
Loading