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

Commit 915883b9 authored by John Reck's avatar John Reck
Browse files

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
parent 5bf85567
Loading
Loading
Loading
Loading
+10 −10
Original line number Diff line number Diff line
@@ -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 = [
+0 −2
Original line number Diff line number Diff line
@@ -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";
@@ -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;
}
+1 −0
Original line number Diff line number Diff line
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ cc_defaults {
        "libskia",
        "libui",
        "libgui",
        "libprotobuf-cpp-full",
        "libprotobuf-cpp-lite",
        "libharfbuzz_ng",
        "libft2",
        "libminikin",
+98 −18
Original line number Diff line number Diff line
@@ -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;
Loading