/*
 * Copyright (C) 2017 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.
 */

#include "GraphicsStatsService.h"

#include <errno.h>
#include <fcntl.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <inttypes.h>
#include <log/log.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <android/util/ProtoOutputStream.h>
#include <stats_event.h>
#include <statslog.h>

#include "JankTracker.h"
#include "protos/graphicsstats.pb.h"

namespace android {
namespace uirenderer {

using namespace google::protobuf;
using namespace uirenderer::protos;

constexpr int32_t sCurrentFileVersion = 1;
constexpr int32_t sHeaderSize = 4;
static_assert(sizeof(sCurrentFileVersion) == sHeaderSize, "Header size is wrong");

constexpr int sHistogramSize = ProfileData::HistogramSize();
constexpr int sGPUHistogramSize = ProfileData::GPUHistogramSize();

static bool mergeProfileDataIntoProto(protos::GraphicsStatsProto* proto, const std::string& package,
                                      int64_t versionCode, int64_t startTime, int64_t endTime,
                                      const ProfileData* data);
static void dumpAsTextToFd(protos::GraphicsStatsProto* proto, int outFd);

class FileDescriptor {
public:
    explicit FileDescriptor(int fd) : mFd(fd) {}
    ~FileDescriptor() {
        if (mFd != -1) {
            close(mFd);
            mFd = -1;
        }
    }
    bool valid() { return mFd != -1; }
    operator int() { return mFd; } // NOLINT(google-explicit-constructor)

private:
    int mFd;
};

class FileOutputStreamLite : public io::ZeroCopyOutputStream {
public:
    explicit 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;

        explicit 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,
                                         protos::GraphicsStatsProto* output) {
    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
        if (err != ENOENT) {
            ALOGW("Failed to open '%s', errno=%d (%s)", path.c_str(), err, strerror(err));
        }
        return false;
    }
    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 == MAP_FAILED) {
        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);
        munmap(addr, sb.st_size);
        return false;
    }

    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 (!success) {
        ALOGW("Parse failed on '%s' error='%s'", path.c_str(),
              output->InitializationErrorString().c_str());
    }
    munmap(addr, sb.st_size);
    return success;
}

bool mergeProfileDataIntoProto(protos::GraphicsStatsProto* proto, const std::string& package,
                               int64_t versionCode, int64_t startTime, int64_t endTime,
                               const ProfileData* data) {
    if (proto->stats_start() == 0 || proto->stats_start() > startTime) {
        proto->set_stats_start(startTime);
    }
    if (proto->stats_end() == 0 || proto->stats_end() < endTime) {
        proto->set_stats_end(endTime);
    }
    proto->set_package_name(package);
    proto->set_version_code(versionCode);
    proto->set_pipeline(data->pipelineType() == RenderPipelineType::SkiaGL ?
            GraphicsStatsProto_PipelineType_GL : GraphicsStatsProto_PipelineType_VULKAN);
    auto summary = proto->mutable_summary();
    summary->set_total_frames(summary->total_frames() + data->totalFrameCount());
    summary->set_janky_frames(summary->janky_frames() + data->jankFrameCount());
    summary->set_missed_vsync_count(summary->missed_vsync_count() +
                                    data->jankTypeCount(kMissedVsync));
    summary->set_high_input_latency_count(summary->high_input_latency_count() +
                                          data->jankTypeCount(kHighInputLatency));
    summary->set_slow_ui_thread_count(summary->slow_ui_thread_count() +
                                      data->jankTypeCount(kSlowUI));
    summary->set_slow_bitmap_upload_count(summary->slow_bitmap_upload_count() +
                                          data->jankTypeCount(kSlowSync));
    summary->set_slow_draw_count(summary->slow_draw_count() + data->jankTypeCount(kSlowRT));
    summary->set_missed_deadline_count(summary->missed_deadline_count() +
                                       data->jankTypeCount(kMissedDeadline));

    bool creatingHistogram = false;
    if (proto->histogram_size() == 0) {
        proto->mutable_histogram()->Reserve(sHistogramSize);
        creatingHistogram = true;
    } else if (proto->histogram_size() != sHistogramSize) {
        ALOGE("Histogram size mismatch, proto is %d expected %d", proto->histogram_size(),
              sHistogramSize);
        return false;
    }
    int index = 0;
    bool hitMergeError = false;
    data->histogramForEach([&](ProfileData::HistogramEntry entry) {
        if (hitMergeError) return;

        protos::GraphicsStatsHistogramBucketProto* bucket;
        if (creatingHistogram) {
            bucket = proto->add_histogram();
            bucket->set_render_millis(entry.renderTimeMs);
        } else {
            bucket = proto->mutable_histogram(index);
            if (bucket->render_millis() != static_cast<int32_t>(entry.renderTimeMs)) {
                ALOGW("Frame time mistmatch %d vs. %u", bucket->render_millis(),
                      entry.renderTimeMs);
                hitMergeError = true;
                return;
            }
        }
        bucket->set_frame_count(bucket->frame_count() + entry.frameCount);
        index++;
    });
    if (hitMergeError) return false;
    // fill in GPU frame time histogram
    creatingHistogram = false;
    if (proto->gpu_histogram_size() == 0) {
        proto->mutable_gpu_histogram()->Reserve(sGPUHistogramSize);
        creatingHistogram = true;
    } else if (proto->gpu_histogram_size() != sGPUHistogramSize) {
        ALOGE("GPU histogram size mismatch, proto is %d expected %d", proto->gpu_histogram_size(),
              sGPUHistogramSize);
        return false;
    }
    index = 0;
    data->histogramGPUForEach([&](ProfileData::HistogramEntry entry) {
        if (hitMergeError) return;

        protos::GraphicsStatsHistogramBucketProto* bucket;
        if (creatingHistogram) {
            bucket = proto->add_gpu_histogram();
            bucket->set_render_millis(entry.renderTimeMs);
        } else {
            bucket = proto->mutable_gpu_histogram(index);
            if (bucket->render_millis() != static_cast<int32_t>(entry.renderTimeMs)) {
                ALOGW("GPU frame time mistmatch %d vs. %u", bucket->render_millis(),
                      entry.renderTimeMs);
                hitMergeError = true;
                return;
            }
        }
        bucket->set_frame_count(bucket->frame_count() + entry.frameCount);
        index++;
    });
    return !hitMergeError;
}

static int32_t findPercentile(protos::GraphicsStatsProto* proto, int percentile) {
    int32_t pos = percentile * proto->summary().total_frames() / 100;
    int32_t remaining = proto->summary().total_frames() - pos;
    for (auto it = proto->histogram().rbegin(); it != proto->histogram().rend(); ++it) {
        remaining -= it->frame_count();
        if (remaining <= 0) {
            return it->render_millis();
        }
    }
    return 0;
}

static int32_t findGPUPercentile(protos::GraphicsStatsProto* proto, int percentile) {
    uint32_t totalGPUFrameCount = 0;  // this is usually  proto->summary().total_frames() - 3.
    for (auto it = proto->gpu_histogram().rbegin(); it != proto->gpu_histogram().rend(); ++it) {
        totalGPUFrameCount += it->frame_count();
    }
    int32_t pos = percentile * totalGPUFrameCount / 100;
    int32_t remaining = totalGPUFrameCount - pos;
    for (auto it = proto->gpu_histogram().rbegin(); it != proto->gpu_histogram().rend(); ++it) {
        remaining -= it->frame_count();
        if (remaining <= 0) {
            return it->render_millis();
        }
    }
    return 0;
}

void dumpAsTextToFd(protos::GraphicsStatsProto* proto, int fd) {
    // This isn't a full validation, just enough that we can deref at will
    if (proto->package_name().empty() || !proto->has_summary()) {
        ALOGW("Skipping dump, invalid package_name() '%s' or summary %d",
              proto->package_name().c_str(), proto->has_summary());
        return;
    }
    dprintf(fd, "\nPackage: %s", proto->package_name().c_str());
    dprintf(fd, "\nVersion: %" PRId64, proto->version_code());
    dprintf(fd, "\nStats since: %" PRId64 "ns", proto->stats_start());
    dprintf(fd, "\nStats end: %" PRId64 "ns", proto->stats_end());
    auto summary = proto->summary();
    dprintf(fd, "\nTotal frames rendered: %d", summary.total_frames());
    dprintf(fd, "\nJanky frames: %d (%.2f%%)", summary.janky_frames(),
            (float)summary.janky_frames() / (float)summary.total_frames() * 100.0f);
    dprintf(fd, "\n50th percentile: %dms", findPercentile(proto, 50));
    dprintf(fd, "\n90th percentile: %dms", findPercentile(proto, 90));
    dprintf(fd, "\n95th percentile: %dms", findPercentile(proto, 95));
    dprintf(fd, "\n99th percentile: %dms", findPercentile(proto, 99));
    dprintf(fd, "\nNumber Missed Vsync: %d", summary.missed_vsync_count());
    dprintf(fd, "\nNumber High input latency: %d", summary.high_input_latency_count());
    dprintf(fd, "\nNumber Slow UI thread: %d", summary.slow_ui_thread_count());
    dprintf(fd, "\nNumber Slow bitmap uploads: %d", summary.slow_bitmap_upload_count());
    dprintf(fd, "\nNumber Slow issue draw commands: %d", summary.slow_draw_count());
    dprintf(fd, "\nNumber Frame deadline missed: %d", summary.missed_deadline_count());
    dprintf(fd, "\nHISTOGRAM:");
    for (const auto& it : proto->histogram()) {
        dprintf(fd, " %dms=%d", it.render_millis(), it.frame_count());
    }
    dprintf(fd, "\n50th gpu percentile: %dms", findGPUPercentile(proto, 50));
    dprintf(fd, "\n90th gpu percentile: %dms", findGPUPercentile(proto, 90));
    dprintf(fd, "\n95th gpu percentile: %dms", findGPUPercentile(proto, 95));
    dprintf(fd, "\n99th gpu percentile: %dms", findGPUPercentile(proto, 99));
    dprintf(fd, "\nGPU HISTOGRAM:");
    for (const auto& it : proto->gpu_histogram()) {
        dprintf(fd, " %dms=%d", it.render_millis(), it.frame_count());
    }
    dprintf(fd, "\n");
}

void GraphicsStatsService::saveBuffer(const std::string& path, const std::string& package,
                                      int64_t versionCode, int64_t startTime, int64_t endTime,
                                      const ProfileData* data) {
    protos::GraphicsStatsProto statsProto;
    if (!parseFromFile(path, &statsProto)) {
        statsProto.Clear();
    }
    if (!mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data)) {
        return;
    }
    // Although we might not have read any data from the file, merging the existing data
    // should always fully-initialize the proto
    if (!statsProto.IsInitialized()) {
        ALOGE("proto initialization error %s", statsProto.InitializationErrorString().c_str());
        return;
    }
    if (statsProto.package_name().empty() || !statsProto.has_summary()) {
        ALOGE("missing package_name() '%s' summary %d", statsProto.package_name().c_str(),
              statsProto.has_summary());
        return;
    }
    int outFd = open(path.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0660);
    if (outFd <= 0) {
        int err = errno;
        ALOGW("Failed to open '%s', error=%d (%s)", path.c_str(), err, strerror(err));
        return;
    }
    int wrote = write(outFd, &sCurrentFileVersion, sHeaderSize);
    if (wrote != sHeaderSize) {
        int err = errno;
        ALOGW("Failed to write header to '%s', returned=%d errno=%d (%s)", path.c_str(), wrote, err,
              strerror(err));
        close(outFd);
        return;
    }
    {
        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)", outFd, path.c_str(),
                  output.GetErrno(), strerror(output.GetErrno()));
            success = false;
        } else if (!success) {
            ALOGW("Serialize failed on '%s' unknown error", path.c_str());
        }
    }
    close(outFd);
}

class GraphicsStatsService::Dump {
public:
    Dump(int outFd, DumpType type) : mFd(outFd), mType(type) {
        if (mFd == -1 && mType == DumpType::Protobuf) {
            mType = DumpType::ProtobufStatsd;
        }
    }
    int fd() { return mFd; }
    DumpType type() { return mType; }
    protos::GraphicsStatsServiceDumpProto& proto() { return mProto; }
    void mergeStat(const protos::GraphicsStatsProto& stat);
    void updateProto();

private:
    // use package name and app version for a key
    typedef std::pair<std::string, int64_t> DumpKey;

    std::map<DumpKey, protos::GraphicsStatsProto> mStats;
    int mFd;
    DumpType mType;
    protos::GraphicsStatsServiceDumpProto mProto;
};

void GraphicsStatsService::Dump::mergeStat(const protos::GraphicsStatsProto& stat) {
    auto dumpKey = std::make_pair(stat.package_name(), stat.version_code());
    auto findIt = mStats.find(dumpKey);
    if (findIt == mStats.end()) {
        mStats[dumpKey] = stat;
    } else {
        auto summary = findIt->second.mutable_summary();
        summary->set_total_frames(summary->total_frames() + stat.summary().total_frames());
        summary->set_janky_frames(summary->janky_frames() + stat.summary().janky_frames());
        summary->set_missed_vsync_count(summary->missed_vsync_count() +
                                        stat.summary().missed_vsync_count());
        summary->set_high_input_latency_count(summary->high_input_latency_count() +
                                              stat.summary().high_input_latency_count());
        summary->set_slow_ui_thread_count(summary->slow_ui_thread_count() +
                                          stat.summary().slow_ui_thread_count());
        summary->set_slow_bitmap_upload_count(summary->slow_bitmap_upload_count() +
                                              stat.summary().slow_bitmap_upload_count());
        summary->set_slow_draw_count(summary->slow_draw_count() + stat.summary().slow_draw_count());
        summary->set_missed_deadline_count(summary->missed_deadline_count() +
                                           stat.summary().missed_deadline_count());
        for (int bucketIndex = 0; bucketIndex < findIt->second.histogram_size(); bucketIndex++) {
            auto bucket = findIt->second.mutable_histogram(bucketIndex);
            bucket->set_frame_count(bucket->frame_count() +
                                    stat.histogram(bucketIndex).frame_count());
        }
        for (int bucketIndex = 0; bucketIndex < findIt->second.gpu_histogram_size();
             bucketIndex++) {
            auto bucket = findIt->second.mutable_gpu_histogram(bucketIndex);
            bucket->set_frame_count(bucket->frame_count() +
                                    stat.gpu_histogram(bucketIndex).frame_count());
        }
        findIt->second.set_stats_start(std::min(findIt->second.stats_start(), stat.stats_start()));
        findIt->second.set_stats_end(std::max(findIt->second.stats_end(), stat.stats_end()));
    }
}

void GraphicsStatsService::Dump::updateProto() {
    for (auto& stat : mStats) {
        mProto.add_stats()->CopyFrom(stat.second);
    }
}

GraphicsStatsService::Dump* GraphicsStatsService::createDump(int outFd, DumpType type) {
    return new Dump(outFd, type);
}

void GraphicsStatsService::addToDump(Dump* dump, const std::string& path,
                                     const std::string& package, int64_t versionCode,
                                     int64_t startTime, int64_t endTime, const ProfileData* data) {
    protos::GraphicsStatsProto statsProto;
    if (!path.empty() && !parseFromFile(path, &statsProto)) {
        statsProto.Clear();
    }
    if (data &&
        !mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data)) {
        return;
    }
    if (!statsProto.IsInitialized()) {
        ALOGW("Failed to load profile data from path '%s' and data %p",
              path.empty() ? "<empty>" : path.c_str(), data);
        return;
    }
    if (dump->type() == DumpType::ProtobufStatsd) {
        dump->mergeStat(statsProto);
    } else if (dump->type() == DumpType::Protobuf) {
        dump->proto().add_stats()->CopyFrom(statsProto);
    } else {
        dumpAsTextToFd(&statsProto, dump->fd());
    }
}

void GraphicsStatsService::addToDump(Dump* dump, const std::string& path) {
    protos::GraphicsStatsProto statsProto;
    if (!parseFromFile(path, &statsProto)) {
        return;
    }
    if (dump->type() == DumpType::ProtobufStatsd) {
        dump->mergeStat(statsProto);
    } else if (dump->type() == DumpType::Protobuf) {
        dump->proto().add_stats()->CopyFrom(statsProto);
    } else {
        dumpAsTextToFd(&statsProto, dump->fd());
    }
}

void GraphicsStatsService::finishDump(Dump* dump) {
    if (dump->type() == DumpType::Protobuf) {
        FileOutputStreamLite stream(dump->fd());
        dump->proto().SerializeToZeroCopyStream(&stream);
    }
    delete dump;
}

using namespace google::protobuf;

// Field ids taken from FrameTimingHistogram message in atoms.proto
#define TIME_MILLIS_BUCKETS_FIELD_NUMBER 1
#define FRAME_COUNTS_FIELD_NUMBER 2

static void writeCpuHistogram(AStatsEvent* event,
                              const uirenderer::protos::GraphicsStatsProto& stat) {
    util::ProtoOutputStream proto;
    for (int bucketIndex = 0; bucketIndex < stat.histogram_size(); bucketIndex++) {
        auto& bucket = stat.histogram(bucketIndex);
        proto.write(android::util::FIELD_TYPE_INT32 | android::util::FIELD_COUNT_REPEATED |
                            TIME_MILLIS_BUCKETS_FIELD_NUMBER /* field id */,
                    (int)bucket.render_millis());
    }
    for (int bucketIndex = 0; bucketIndex < stat.histogram_size(); bucketIndex++) {
        auto& bucket = stat.histogram(bucketIndex);
        proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED |
                            FRAME_COUNTS_FIELD_NUMBER /* field id */,
                    (long long)bucket.frame_count());
    }
    std::vector<uint8_t> outVector;
    proto.serializeToVector(&outVector);
    AStatsEvent_writeByteArray(event, outVector.data(), outVector.size());
}

static void writeGpuHistogram(AStatsEvent* event,
                              const uirenderer::protos::GraphicsStatsProto& stat) {
    util::ProtoOutputStream proto;
    for (int bucketIndex = 0; bucketIndex < stat.gpu_histogram_size(); bucketIndex++) {
        auto& bucket = stat.gpu_histogram(bucketIndex);
        proto.write(android::util::FIELD_TYPE_INT32 | android::util::FIELD_COUNT_REPEATED |
                            TIME_MILLIS_BUCKETS_FIELD_NUMBER /* field id */,
                    (int)bucket.render_millis());
    }
    for (int bucketIndex = 0; bucketIndex < stat.gpu_histogram_size(); bucketIndex++) {
        auto& bucket = stat.gpu_histogram(bucketIndex);
        proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED |
                            FRAME_COUNTS_FIELD_NUMBER /* field id */,
                    (long long)bucket.frame_count());
    }
    std::vector<uint8_t> outVector;
    proto.serializeToVector(&outVector);
    AStatsEvent_writeByteArray(event, outVector.data(), outVector.size());
}


void GraphicsStatsService::finishDumpInMemory(Dump* dump, AStatsEventList* data,
                                              bool lastFullDay) {
    dump->updateProto();
    auto& serviceDump = dump->proto();
    for (int stat_index = 0; stat_index < serviceDump.stats_size(); stat_index++) {
        auto& stat = serviceDump.stats(stat_index);
        AStatsEvent* event = AStatsEventList_addStatsEvent(data);
        AStatsEvent_setAtomId(event, android::util::GRAPHICS_STATS);
        AStatsEvent_writeString(event, stat.package_name().c_str());
        AStatsEvent_writeInt64(event, (int64_t)stat.version_code());
        AStatsEvent_writeInt64(event, (int64_t)stat.stats_start());
        AStatsEvent_writeInt64(event, (int64_t)stat.stats_end());
        AStatsEvent_writeInt32(event, (int32_t)stat.pipeline());
        AStatsEvent_writeInt32(event, (int32_t)stat.summary().total_frames());
        AStatsEvent_writeInt32(event, (int32_t)stat.summary().missed_vsync_count());
        AStatsEvent_writeInt32(event, (int32_t)stat.summary().high_input_latency_count());
        AStatsEvent_writeInt32(event, (int32_t)stat.summary().slow_ui_thread_count());
        AStatsEvent_writeInt32(event, (int32_t)stat.summary().slow_bitmap_upload_count());
        AStatsEvent_writeInt32(event, (int32_t)stat.summary().slow_draw_count());
        AStatsEvent_writeInt32(event, (int32_t)stat.summary().missed_deadline_count());
        writeCpuHistogram(event, stat);
        writeGpuHistogram(event, stat);
        // TODO: fill in UI mainline module version, when the feature is available.
        AStatsEvent_writeInt64(event, (int64_t)0);
        AStatsEvent_writeBool(event, !lastFullDay);
        AStatsEvent_build(event);
    }
}


} /* namespace uirenderer */
} /* namespace android */
