diff options
author | John Reck <jreck@google.com> | 2017-05-03 10:27:20 -0700 |
---|---|---|
committer | John Reck <jreck@google.com> | 2017-05-12 10:44:46 -0700 |
commit | 915883b9f0c88371f416894366536d120d9cf7ad (patch) | |
tree | 5759d2d2c49d5c93cec774db21dc1ed2904a5f5d /libs/hwui/service/GraphicsStatsService.cpp | |
parent | 5bf855675c9e54f472d44f44f6b056aad985c569 (diff) |
Switch to protobuf lite
Fixes: 36272398
Protobuf lite isn't just smaller, it also doesn't
have the problematic DescriptorPool at all. So no
need to switch this to a shared library.
Test: hwui_unit_test passes and doesn't crash. CTS incident tests pass
as well
Change-Id: I2693ba2c47af89a5c561c4f63cc7e1f509ebbbec
Diffstat (limited to 'libs/hwui/service/GraphicsStatsService.cpp')
-rw-r--r-- | libs/hwui/service/GraphicsStatsService.cpp | 116 |
1 files changed, 98 insertions, 18 deletions
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp index ab6420e990f9..87eaa6add459 100644 --- a/libs/hwui/service/GraphicsStatsService.cpp +++ b/libs/hwui/service/GraphicsStatsService.cpp @@ -19,7 +19,7 @@ #include "JankTracker.h" #include <frameworks/base/core/proto/android/service/graphicsstats.pb.h> -#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> #include <log/log.h> #include <inttypes.h> @@ -27,6 +27,7 @@ #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> +#include <sys/mman.h> namespace android { namespace uirenderer { @@ -46,10 +47,74 @@ static void mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const ProfileData* data); static void dumpAsTextToFd(service::GraphicsStatsProto* proto, int outFd); +class FileDescriptor { +public: + FileDescriptor(int fd) : mFd(fd) {} + ~FileDescriptor() { + if (mFd != -1) { + close(mFd); + mFd = -1; + } + } + bool valid() { return mFd != -1; } + operator int() { return mFd; } +private: + int mFd; +}; + +class FileOutputStreamLite : public io::ZeroCopyOutputStream { +public: + FileOutputStreamLite(int fd) : mCopyAdapter(fd), mImpl(&mCopyAdapter) {} + virtual ~FileOutputStreamLite() {} + + int GetErrno() { return mCopyAdapter.mErrno; } + + virtual bool Next(void** data, int* size) override { + return mImpl.Next(data, size); + } + + virtual void BackUp(int count) override { + mImpl.BackUp(count); + } + + virtual int64 ByteCount() const override { + return mImpl.ByteCount(); + } + + bool Flush() { + return mImpl.Flush(); + } + +private: + struct FDAdapter : public io::CopyingOutputStream { + int mFd; + int mErrno = 0; + + FDAdapter(int fd) : mFd(fd) {} + virtual ~FDAdapter() {} + + virtual bool Write(const void* buffer, int size) override { + int ret; + while (size) { + ret = TEMP_FAILURE_RETRY( write(mFd, buffer, size) ); + if (ret <= 0) { + mErrno = errno; + return false; + } + size -= ret; + } + return true; + } + }; + + FileOutputStreamLite::FDAdapter mCopyAdapter; + io::CopyingOutputStreamAdaptor mImpl; +}; + bool GraphicsStatsService::parseFromFile(const std::string& path, service::GraphicsStatsProto* output) { - int fd = open(path.c_str(), O_RDONLY); - if (fd == -1) { + FileDescriptor fd{open(path.c_str(), O_RDONLY)}; + if (!fd.valid()) { int err = errno; // The file not existing is normal for addToDump(), so only log if // we get an unexpected error @@ -58,26 +123,41 @@ bool GraphicsStatsService::parseFromFile(const std::string& path, service::Graph } return false; } - uint32_t file_version; - ssize_t bytesRead = read(fd, &file_version, sHeaderSize); - if (bytesRead != sHeaderSize || file_version != sCurrentFileVersion) { - ALOGW("Failed to read '%s', bytesRead=%zd file_version=%d", path.c_str(), bytesRead, - file_version); - close(fd); + struct stat sb; + if (fstat(fd, &sb) || sb.st_size < sHeaderSize) { + int err = errno; + // The file not existing is normal for addToDump(), so only log if + // we get an unexpected error + if (err != ENOENT) { + ALOGW("Failed to fstat '%s', errno=%d (%s) (st_size %d)", path.c_str(), err, + strerror(err), (int) sb.st_size); + } + return false; + } + void* addr = mmap(nullptr, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (!addr) { + int err = errno; + // The file not existing is normal for addToDump(), so only log if + // we get an unexpected error + if (err != ENOENT) { + ALOGW("Failed to mmap '%s', errno=%d (%s)", path.c_str(), err, strerror(err)); + } + return false; + } + uint32_t file_version = *reinterpret_cast<uint32_t*>(addr); + if (file_version != sCurrentFileVersion) { + ALOGW("file_version mismatch! expected %d got %d", sCurrentFileVersion, file_version); return false; } - io::FileInputStream input(fd); + void* data = reinterpret_cast<uint8_t*>(addr) + sHeaderSize; + int dataSize = sb.st_size - sHeaderSize; + io::ArrayInputStream input{data, dataSize}; bool success = output->ParseFromZeroCopyStream(&input); - if (input.GetErrno() != 0) { - ALOGW("Error reading from fd=%d, path='%s' err=%d (%s)", - fd, path.c_str(), input.GetErrno(), strerror(input.GetErrno())); - success = false; - } else if (!success) { + if (!success) { ALOGW("Parse failed on '%s' error='%s'", path.c_str(), output->InitializationErrorString().c_str()); } - close(fd); return success; } @@ -212,7 +292,7 @@ void GraphicsStatsService::saveBuffer(const std::string& path, const std::string return; } { - io::FileOutputStream output(outFd); + FileOutputStreamLite output(outFd); bool success = statsProto.SerializeToZeroCopyStream(&output) && output.Flush(); if (output.GetErrno() != 0) { ALOGW("Error writing to fd=%d, path='%s' err=%d (%s)", @@ -277,7 +357,7 @@ void GraphicsStatsService::addToDump(Dump* dump, const std::string& path) { void GraphicsStatsService::finishDump(Dump* dump) { if (dump->type() == DumpType::Protobuf) { - io::FileOutputStream stream(dump->fd()); + FileOutputStreamLite stream(dump->fd()); dump->proto().SerializeToZeroCopyStream(&stream); } delete dump; |