Loading Android.bp +10 −10 Original line number Diff line number Diff line Loading @@ -28,26 +28,26 @@ cc_library { proto: { type: "full", }, srcs: [ "core/proto/**/*.proto", "libs/incident/**/*.proto", ], }, android: { proto: { type: "lite", }, // We only build the protos that are optimized for the lite // runtime, as well as the only protos that are actually // needed by the device. srcs: [ "core/proto/android/service/graphicsstats.proto", ], shared: { // The proto files generate full protos, but we only use // them as lite on device. This works fine for a static // library, where the unused full symbols are stripped, // but fails if it is linked as a standalone shared // library because it is missing the full runtime. enabled: false, }, }, }, srcs: [ "core/proto/**/*.proto", "libs/incident/**/*.proto", ], } subdirs = [ Loading core/proto/android/os/incident.proto +0 −2 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ option java_outer_classname = "IncidentProtoMetadata"; import "frameworks/base/libs/incident/proto/android/privacy.proto"; import "frameworks/base/core/proto/android/service/appwidget.proto"; import "frameworks/base/core/proto/android/service/battery.proto"; import "frameworks/base/core/proto/android/service/graphicsstats.proto"; import "frameworks/base/core/proto/android/service/fingerprint.proto"; import "frameworks/base/core/proto/android/service/diskstats.proto"; import "frameworks/base/core/proto/android/service/netstats.proto"; Loading Loading @@ -66,5 +65,4 @@ message IncidentProto { android.service.notification.NotificationServiceDumpProto notification = 3004; android.service.pm.PackageServiceDumpProto package = 3008; android.service.power.PowerServiceDumpProto power = 3009; android.service.GraphicsStatsServiceDumpProto graphicsstats = 3005; } core/proto/android/service/graphicsstats.proto +1 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ package android.service; option java_multiple_files = true; option java_outer_classname = "GraphicsStatsServiceProto"; option optimize_for = LITE_RUNTIME; message GraphicsStatsServiceDumpProto { repeated GraphicsStatsProto stats = 1; Loading libs/hwui/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -62,7 +62,7 @@ cc_defaults { "libskia", "libui", "libgui", "libprotobuf-cpp-full", "libprotobuf-cpp-lite", "libharfbuzz_ng", "libft2", "libminikin", Loading libs/hwui/service/GraphicsStatsService.cpp +98 −18 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -27,6 +27,7 @@ #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> namespace android { namespace uirenderer { Loading @@ -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 Loading @@ -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; } Loading Loading @@ -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)", Loading Loading @@ -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; Loading Loading
Android.bp +10 −10 Original line number Diff line number Diff line Loading @@ -28,26 +28,26 @@ cc_library { proto: { type: "full", }, srcs: [ "core/proto/**/*.proto", "libs/incident/**/*.proto", ], }, android: { proto: { type: "lite", }, // We only build the protos that are optimized for the lite // runtime, as well as the only protos that are actually // needed by the device. srcs: [ "core/proto/android/service/graphicsstats.proto", ], shared: { // The proto files generate full protos, but we only use // them as lite on device. This works fine for a static // library, where the unused full symbols are stripped, // but fails if it is linked as a standalone shared // library because it is missing the full runtime. enabled: false, }, }, }, srcs: [ "core/proto/**/*.proto", "libs/incident/**/*.proto", ], } subdirs = [ Loading
core/proto/android/os/incident.proto +0 −2 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ option java_outer_classname = "IncidentProtoMetadata"; import "frameworks/base/libs/incident/proto/android/privacy.proto"; import "frameworks/base/core/proto/android/service/appwidget.proto"; import "frameworks/base/core/proto/android/service/battery.proto"; import "frameworks/base/core/proto/android/service/graphicsstats.proto"; import "frameworks/base/core/proto/android/service/fingerprint.proto"; import "frameworks/base/core/proto/android/service/diskstats.proto"; import "frameworks/base/core/proto/android/service/netstats.proto"; Loading Loading @@ -66,5 +65,4 @@ message IncidentProto { android.service.notification.NotificationServiceDumpProto notification = 3004; android.service.pm.PackageServiceDumpProto package = 3008; android.service.power.PowerServiceDumpProto power = 3009; android.service.GraphicsStatsServiceDumpProto graphicsstats = 3005; }
core/proto/android/service/graphicsstats.proto +1 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ package android.service; option java_multiple_files = true; option java_outer_classname = "GraphicsStatsServiceProto"; option optimize_for = LITE_RUNTIME; message GraphicsStatsServiceDumpProto { repeated GraphicsStatsProto stats = 1; Loading
libs/hwui/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -62,7 +62,7 @@ cc_defaults { "libskia", "libui", "libgui", "libprotobuf-cpp-full", "libprotobuf-cpp-lite", "libharfbuzz_ng", "libft2", "libminikin", Loading
libs/hwui/service/GraphicsStatsService.cpp +98 −18 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -27,6 +27,7 @@ #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> namespace android { namespace uirenderer { Loading @@ -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 Loading @@ -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; } Loading Loading @@ -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)", Loading Loading @@ -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; Loading