/*
 * Copyright (C) 2016 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.
 */
#define DEBUG false
#include "Log.h"

#include "Section.h"

#include <dirent.h>
#include <errno.h>
#include <mutex>
#include <set>
#include <thread>

#include <android-base/file.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android/util/protobuf.h>
#include <android/util/ProtoOutputStream.h>
#include <binder/IServiceManager.h>
#include <debuggerd/client.h>
#include <dumputils/dump_utils.h>
#include <log/log_event_list.h>
#include <log/log_read.h>
#include <log/logprint.h>
#include <private/android_logger.h>
#include <sys/mman.h>

#include "FdBuffer.h"
#include "Privacy.h"
#include "frameworks/base/core/proto/android/os/backtrace.proto.h"
#include "frameworks/base/core/proto/android/os/data.proto.h"
#include "frameworks/base/core/proto/android/util/log.proto.h"
#include "frameworks/base/core/proto/android/util/textdump.proto.h"
#include "incidentd_util.h"

namespace android {
namespace os {
namespace incidentd {

using namespace android::base;
using namespace android::util;

// special section ids
const int FIELD_ID_INCIDENT_METADATA = 2;

// incident section parameters
const char INCIDENT_HELPER[] = "/system/bin/incident_helper";
const char* GZIP[] = {"/system/bin/gzip", NULL};

static pid_t fork_execute_incident_helper(const int id, Fpipe* p2cPipe, Fpipe* c2pPipe) {
    const char* ihArgs[]{INCIDENT_HELPER, "-s", String8::format("%d", id).string(), NULL};
    return fork_execute_cmd(const_cast<char**>(ihArgs), p2cPipe, c2pPipe);
}

bool section_requires_specific_mention(int sectionId) {
    switch (sectionId) {
        case 3025: // restricted_images
            return true;
        case 3026: // system_trace
            return true;
        default:
            return false;
    }
}

// ================================================================================
Section::Section(int i, int64_t timeoutMs)
    : id(i),
      timeoutMs(timeoutMs) {
}

Section::~Section() {}

// ================================================================================
static inline bool isSysfs(const char* filename) { return strncmp(filename, "/sys/", 5) == 0; }

FileSection::FileSection(int id, const char* filename, const int64_t timeoutMs)
    : Section(id, timeoutMs), mFilename(filename) {
    name = "file ";
    name += filename;
    mIsSysfs = isSysfs(filename);
}

FileSection::~FileSection() {}

status_t FileSection::Execute(ReportWriter* writer) const {
    // read from mFilename first, make sure the file is available
    // add O_CLOEXEC to make sure it is closed when exec incident helper
    unique_fd fd(open(mFilename, O_RDONLY | O_CLOEXEC));
    if (fd.get() == -1) {
        ALOGW("[%s] failed to open file", this->name.string());
        // There may be some devices/architectures that won't have the file.
        // Just return here without an error.
        return NO_ERROR;
    }

    Fpipe p2cPipe;
    Fpipe c2pPipe;
    // initiate pipes to pass data to/from incident_helper
    if (!p2cPipe.init() || !c2pPipe.init()) {
        ALOGW("[%s] failed to setup pipes", this->name.string());
        return -errno;
    }

    pid_t pid = fork_execute_incident_helper(this->id, &p2cPipe, &c2pPipe);
    if (pid == -1) {
        ALOGW("[%s] failed to fork", this->name.string());
        return -errno;
    }

    // parent process
    FdBuffer buffer;
    status_t readStatus = buffer.readProcessedDataInStream(fd.get(), std::move(p2cPipe.writeFd()),
                                                           std::move(c2pPipe.readFd()),
                                                           this->timeoutMs, mIsSysfs);
    writer->setSectionStats(buffer);
    if (readStatus != NO_ERROR || buffer.timedOut()) {
        ALOGW("[%s] failed to read data from incident helper: %s, timedout: %s",
              this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
        kill_child(pid);
        return readStatus;
    }

    status_t ihStatus = wait_child(pid);
    if (ihStatus != NO_ERROR) {
        ALOGW("[%s] abnormal child process: %s", this->name.string(), strerror(-ihStatus));
        return OK; // Not a fatal error.
    }

    return writer->writeSection(buffer);
}
// ================================================================================
GZipSection::GZipSection(int id, const char* filename, ...) : Section(id) {
    va_list args;
    va_start(args, filename);
    mFilenames = varargs(filename, args);
    va_end(args);
    name = "gzip";
    for (int i = 0; mFilenames[i] != NULL; i++) {
        name += " ";
        name += mFilenames[i];
    }
}

GZipSection::~GZipSection() { free(mFilenames); }

status_t GZipSection::Execute(ReportWriter* writer) const {
    // Reads the files in order, use the first available one.
    int index = 0;
    unique_fd fd;
    while (mFilenames[index] != NULL) {
        fd.reset(open(mFilenames[index], O_RDONLY | O_CLOEXEC));
        if (fd.get() != -1) {
            break;
        }
        ALOGW("GZipSection failed to open file %s", mFilenames[index]);
        index++;  // look at the next file.
    }
    if (fd.get() == -1) {
        ALOGW("[%s] can't open all the files", this->name.string());
        return NO_ERROR;  // e.g. LAST_KMSG will reach here in user build.
    }
    FdBuffer buffer;
    Fpipe p2cPipe;
    Fpipe c2pPipe;
    // initiate pipes to pass data to/from gzip
    if (!p2cPipe.init() || !c2pPipe.init()) {
        ALOGW("[%s] failed to setup pipes", this->name.string());
        return -errno;
    }

    pid_t pid = fork_execute_cmd((char* const*)GZIP, &p2cPipe, &c2pPipe);
    if (pid == -1) {
        ALOGW("[%s] failed to fork", this->name.string());
        return -errno;
    }
    // parent process

    // construct Fdbuffer to output GZippedfileProto, the reason to do this instead of using
    // ProtoOutputStream is to avoid allocation of another buffer inside ProtoOutputStream.
    sp<EncodedBuffer> internalBuffer = buffer.data();
    internalBuffer->writeHeader((uint32_t)GZippedFileProto::FILENAME, WIRE_TYPE_LENGTH_DELIMITED);
    size_t fileLen = strlen(mFilenames[index]);
    internalBuffer->writeRawVarint32(fileLen);
    for (size_t i = 0; i < fileLen; i++) {
        internalBuffer->writeRawByte(mFilenames[index][i]);
    }
    internalBuffer->writeHeader((uint32_t)GZippedFileProto::GZIPPED_DATA,
                                WIRE_TYPE_LENGTH_DELIMITED);
    size_t editPos = internalBuffer->wp()->pos();
    internalBuffer->wp()->move(8);  // reserve 8 bytes for the varint of the data size.
    size_t dataBeginAt = internalBuffer->wp()->pos();
    VLOG("[%s] editPos=%zu, dataBeginAt=%zu", this->name.string(), editPos, dataBeginAt);

    status_t readStatus = buffer.readProcessedDataInStream(
            fd.get(), std::move(p2cPipe.writeFd()), std::move(c2pPipe.readFd()), this->timeoutMs,
            isSysfs(mFilenames[index]));
    writer->setSectionStats(buffer);
    if (readStatus != NO_ERROR || buffer.timedOut()) {
        ALOGW("[%s] failed to read data from gzip: %s, timedout: %s", this->name.string(),
              strerror(-readStatus), buffer.timedOut() ? "true" : "false");
        kill_child(pid);
        return readStatus;
    }

    status_t gzipStatus = wait_child(pid);
    if (gzipStatus != NO_ERROR) {
        ALOGW("[%s] abnormal child process: %s", this->name.string(), strerror(-gzipStatus));
        return gzipStatus;
    }
    // Revisit the actual size from gzip result and edit the internal buffer accordingly.
    size_t dataSize = buffer.size() - dataBeginAt;
    internalBuffer->wp()->rewind()->move(editPos);
    internalBuffer->writeRawVarint32(dataSize);
    internalBuffer->copy(dataBeginAt, dataSize);

    return writer->writeSection(buffer);
}

// ================================================================================
struct WorkerThreadData : public virtual RefBase {
    const WorkerThreadSection* section;
    Fpipe pipe;

    // Lock protects these fields
    std::mutex lock;
    bool workerDone;
    status_t workerError;

    explicit WorkerThreadData(const WorkerThreadSection* section);
    virtual ~WorkerThreadData();
};

WorkerThreadData::WorkerThreadData(const WorkerThreadSection* sec)
    : section(sec), workerDone(false), workerError(NO_ERROR) {}

WorkerThreadData::~WorkerThreadData() {}

// ================================================================================
WorkerThreadSection::WorkerThreadSection(int id, const int64_t timeoutMs)
    : Section(id, timeoutMs) {}

WorkerThreadSection::~WorkerThreadSection() {}

void sigpipe_handler(int signum) {
    if (signum == SIGPIPE) {
        ALOGE("Wrote to a broken pipe\n");
    } else {
        ALOGE("Received unexpected signal: %d\n", signum);
    }
}

status_t WorkerThreadSection::Execute(ReportWriter* writer) const {
    // Create shared data and pipe. Don't put data on the stack since this thread may exit early.
    sp<WorkerThreadData> data = new WorkerThreadData(this);
    if (!data->pipe.init()) {
        return -errno;
    }
    data->incStrong(this);
    std::thread([data, this]() {
        // Don't crash the service if writing to a closed pipe (may happen if dumping times out)
        signal(SIGPIPE, sigpipe_handler);
        status_t err = data->section->BlockingCall(data->pipe.writeFd());
        {
            std::scoped_lock<std::mutex> lock(data->lock);
            data->workerDone = true;
            data->workerError = err;
            // unique_fd is not thread safe. If we don't lock it, reset() may pause half way while
            // the other thread executes to the end, calling ~Fpipe, which is a race condition.
            data->pipe.writeFd().reset();
        }
        data->decStrong(this);
    }).detach();

    // Loop reading until either the timeout or the worker side is done (i.e. eof).
    status_t err = NO_ERROR;
    bool workerDone = false;
    FdBuffer buffer;
    err = buffer.read(data->pipe.readFd().get(), this->timeoutMs);
    if (err != NO_ERROR) {
        ALOGE("[%s] reader failed with error '%s'", this->name.string(), strerror(-err));
    }

    // If the worker side is finished, then return its error (which may overwrite
    // our possible error -- but it's more interesting anyway). If not, then we timed out.
    {
        std::scoped_lock<std::mutex> lock(data->lock);
        data->pipe.close();
        if (data->workerError != NO_ERROR) {
            err = data->workerError;
            ALOGE("[%s] worker failed with error '%s'", this->name.string(), strerror(-err));
        }
        workerDone = data->workerDone;
    }

    writer->setSectionStats(buffer);
    if (err != NO_ERROR) {
        char errMsg[128];
        snprintf(errMsg, 128, "[%s] failed with error '%s'",
            this->name.string(), strerror(-err));
        writer->error(this, err, "WorkerThreadSection failed.");
        return NO_ERROR;
    }
    if (buffer.truncated()) {
        ALOGW("[%s] too large, truncating", this->name.string());
        // Do not write a truncated section. It won't pass through the PrivacyFilter.
        return NO_ERROR;
    }
    if (!workerDone || buffer.timedOut()) {
        ALOGW("[%s] timed out", this->name.string());
        return NO_ERROR;
    }

    // Write the data that was collected
    return writer->writeSection(buffer);
}

// ================================================================================
CommandSection::CommandSection(int id, const int64_t timeoutMs, const char* command, ...)
    : Section(id, timeoutMs) {
    va_list args;
    va_start(args, command);
    mCommand = varargs(command, args);
    va_end(args);
    name = "cmd";
    for (int i = 0; mCommand[i] != NULL; i++) {
        name += " ";
        name += mCommand[i];
    }
}

CommandSection::CommandSection(int id, const char* command, ...) : Section(id) {
    va_list args;
    va_start(args, command);
    mCommand = varargs(command, args);
    va_end(args);
    name = "cmd";
    for (int i = 0; mCommand[i] != NULL; i++) {
        name += " ";
        name += mCommand[i];
    }
}

CommandSection::~CommandSection() { free(mCommand); }

status_t CommandSection::Execute(ReportWriter* writer) const {
    Fpipe cmdPipe;
    Fpipe ihPipe;

    if (!cmdPipe.init() || !ihPipe.init()) {
        ALOGW("[%s] failed to setup pipes", this->name.string());
        return -errno;
    }

    pid_t cmdPid = fork_execute_cmd((char* const*)mCommand, NULL, &cmdPipe);
    if (cmdPid == -1) {
        ALOGW("[%s] failed to fork", this->name.string());
        return -errno;
    }
    pid_t ihPid = fork_execute_incident_helper(this->id, &cmdPipe, &ihPipe);
    if (ihPid == -1) {
        ALOGW("[%s] failed to fork", this->name.string());
        return -errno;
    }

    cmdPipe.writeFd().reset();
    FdBuffer buffer;
    status_t readStatus = buffer.read(ihPipe.readFd().get(), this->timeoutMs);
    writer->setSectionStats(buffer);
    if (readStatus != NO_ERROR || buffer.timedOut()) {
        ALOGW("[%s] failed to read data from incident helper: %s, timedout: %s",
              this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
        kill_child(cmdPid);
        kill_child(ihPid);
        return readStatus;
    }

    // Waiting for command here has one trade-off: the failed status of command won't be detected
    // until buffer timeout, but it has advatage on starting the data stream earlier.
    status_t cmdStatus = wait_child(cmdPid);
    status_t ihStatus = wait_child(ihPid);
    if (cmdStatus != NO_ERROR || ihStatus != NO_ERROR) {
        ALOGW("[%s] abnormal child processes, return status: command: %s, incident helper: %s",
              this->name.string(), strerror(-cmdStatus), strerror(-ihStatus));
        // Not a fatal error.
        return NO_ERROR;
    }

    return writer->writeSection(buffer);
}

// ================================================================================
DumpsysSection::DumpsysSection(int id, const char* service, ...)
    : WorkerThreadSection(id, REMOTE_CALL_TIMEOUT_MS), mService(service) {
    name = "dumpsys ";
    name += service;

    va_list args;
    va_start(args, service);
    while (true) {
        const char* arg = va_arg(args, const char*);
        if (arg == NULL) {
            break;
        }
        mArgs.add(String16(arg));
        name += " ";
        name += arg;
    }
    va_end(args);
}

DumpsysSection::~DumpsysSection() {}

status_t DumpsysSection::BlockingCall(unique_fd& pipeWriteFd) const {
    // checkService won't wait for the service to show up like getService will.
    sp<IBinder> service = defaultServiceManager()->checkService(mService);

    if (service == NULL) {
        ALOGW("DumpsysSection: Can't lookup service: %s", String8(mService).string());
        return NAME_NOT_FOUND;
    }

    service->dump(pipeWriteFd.get(), mArgs);

    return NO_ERROR;
}

// ================================================================================
TextDumpsysSection::TextDumpsysSection(int id, const char* service, ...)
        :Section(id), mService(service) {
    name = "dumpsys ";
    name += service;

    va_list args;
    va_start(args, service);
    while (true) {
        const char* arg = va_arg(args, const char*);
        if (arg == NULL) {
            break;
        }
        mArgs.add(String16(arg));
        name += " ";
        name += arg;
    }
    va_end(args);
}

TextDumpsysSection::~TextDumpsysSection() {}

status_t TextDumpsysSection::Execute(ReportWriter* writer) const {
    // checkService won't wait for the service to show up like getService will.
    sp<IBinder> service = defaultServiceManager()->checkService(mService);
    if (service == NULL) {
        ALOGW("TextDumpsysSection: Can't lookup service: %s", String8(mService).string());
        return NAME_NOT_FOUND;
    }

    // Create pipe
    Fpipe dumpPipe;
    if (!dumpPipe.init()) {
        ALOGW("[%s] failed to setup pipe", this->name.string());
        return -errno;
    }

    // Run dumping thread
    const uint64_t start = Nanotime();
    std::thread worker([&]() {
        // Don't crash the service if writing to a closed pipe (may happen if dumping times out)
        signal(SIGPIPE, sigpipe_handler);
        status_t err = service->dump(dumpPipe.writeFd().get(), mArgs);
        if (err != OK) {
            ALOGW("[%s] dump thread failed. Error: %s", this->name.string(), strerror(-err));
        }
        dumpPipe.writeFd().reset();
    });

    // Collect dump content
    FdBuffer buffer;
    ProtoOutputStream proto;
    proto.write(TextDumpProto::COMMAND, std::string(name.string()));
    proto.write(TextDumpProto::DUMP_DURATION_NS, int64_t(Nanotime() - start));
    buffer.write(proto.data());

    sp<EncodedBuffer> internalBuffer = buffer.data();
    internalBuffer->writeHeader((uint32_t)TextDumpProto::CONTENT, WIRE_TYPE_LENGTH_DELIMITED);
    size_t editPos = internalBuffer->wp()->pos();
    internalBuffer->wp()->move(8); // reserve 8 bytes for the varint of the data size
    size_t dataBeginPos = internalBuffer->wp()->pos();

    status_t readStatus = buffer.read(dumpPipe.readFd(), this->timeoutMs);
    dumpPipe.readFd().reset();
    writer->setSectionStats(buffer);
    if (readStatus != OK || buffer.timedOut()) {
        ALOGW("[%s] failed to read from dumpsys: %s, timedout: %s", this->name.string(),
              strerror(-readStatus), buffer.timedOut() ? "true" : "false");
        worker.detach();
        return readStatus;
    }
    worker.join(); // wait for worker to finish

    // Revisit the actual size from dumpsys and edit the internal buffer accordingly.
    size_t dumpSize = buffer.size() - dataBeginPos;
    internalBuffer->wp()->rewind()->move(editPos);
    internalBuffer->writeRawVarint32(dumpSize);
    internalBuffer->copy(dataBeginPos, dumpSize);

    return writer->writeSection(buffer);
}

// ================================================================================
// initialization only once in Section.cpp.
map<log_id_t, log_time> LogSection::gLastLogsRetrieved;

LogSection::LogSection(int id, const char* logID, ...) : WorkerThreadSection(id), mLogMode(logModeBase) {
    name = "logcat -b ";
    name += logID;

    va_list args;
    va_start(args, logID);
    mLogID = android_name_to_log_id(logID);
    while(true) {
        const char* arg = va_arg(args, const char*);
        if (arg == NULL) {
            break;
        }
        if (!strcmp(arg, "-L")) {
          // Read from last logcat buffer
          mLogMode = mLogMode | ANDROID_LOG_PSTORE;
        }
        name += " ";
        name += arg;
    }
    va_end(args);

    switch (mLogID) {
        case LOG_ID_EVENTS:
        case LOG_ID_STATS:
        case LOG_ID_SECURITY:
            mBinary = true;
            break;
        default:
            mBinary = false;
    }
}

LogSection::~LogSection() {}

static size_t trimTail(char const* buf, size_t len) {
    while (len > 0) {
        char c = buf[len - 1];
        if (c == '\0' || c == ' ' || c == '\n' || c == '\r' || c == ':') {
            len--;
        } else {
            break;
        }
    }
    return len;
}

static inline int32_t get4LE(uint8_t const* src) {
    return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
}

status_t LogSection::BlockingCall(unique_fd& pipeWriteFd) const {
    // heap profile shows that liblog malloc & free significant amount of memory in this process.
    // Hence forking a new process to prevent memory fragmentation.
    pid_t pid = fork();
    if (pid < 0) {
        ALOGW("[%s] failed to fork", this->name.string());
        return errno;
    }
    if (pid > 0) {
        return wait_child(pid, this->timeoutMs);
    }
    // Open log buffer and getting logs since last retrieved time if any.
    unique_ptr<logger_list, void (*)(logger_list*)> loggers(
            gLastLogsRetrieved.find(mLogID) == gLastLogsRetrieved.end()
                    ? android_logger_list_alloc(mLogMode, 0, 0)
                    : android_logger_list_alloc_time(mLogMode, gLastLogsRetrieved[mLogID], 0),
            android_logger_list_free);

    if (android_logger_open(loggers.get(), mLogID) == NULL) {
        ALOGE("[%s] Can't get logger.", this->name.string());
        _exit(EXIT_FAILURE);
    }

    log_msg msg;
    log_time lastTimestamp(0);

    ProtoOutputStream proto;
    status_t err = OK;
    while (true) {  // keeps reading until logd buffer is fully read.
        status_t status = android_logger_list_read(loggers.get(), &msg);
        // status = 0 - no content, unexpected connection drop or EOF.
        // status = +ive number - size of retrieved data from logger
        // status = -ive number, OS supplied error _except_ for -EAGAIN
        // status = -EAGAIN, graceful indication for ANDRODI_LOG_NONBLOCK that this is the end.
        if (status <= 0) {
            if (status != -EAGAIN) {
                ALOGW("[%s] fails to read a log_msg.\n", this->name.string());
                err = -status;
            }
            break;
        }
        if (mBinary) {
            // remove the first uint32 which is tag's index in event log tags
            android_log_context context = create_android_log_parser(msg.msg() + sizeof(uint32_t),
                                                                    msg.len() - sizeof(uint32_t));
            android_log_list_element elem;

            lastTimestamp.tv_sec = msg.entry.sec;
            lastTimestamp.tv_nsec = msg.entry.nsec;

            // format a BinaryLogEntry
            uint64_t token = proto.start(LogProto::BINARY_LOGS);
            proto.write(BinaryLogEntry::SEC, (int32_t)msg.entry.sec);
            proto.write(BinaryLogEntry::NANOSEC, (int32_t)msg.entry.nsec);
            proto.write(BinaryLogEntry::UID, (int)msg.entry.uid);
            proto.write(BinaryLogEntry::PID, msg.entry.pid);
            proto.write(BinaryLogEntry::TID, (int32_t)msg.entry.tid);
            proto.write(BinaryLogEntry::TAG_INDEX,
                        get4LE(reinterpret_cast<uint8_t const*>(msg.msg())));
            do {
                elem = android_log_read_next(context);
                uint64_t elemToken = proto.start(BinaryLogEntry::ELEMS);
                switch (elem.type) {
                    case EVENT_TYPE_INT:
                        proto.write(BinaryLogEntry::Elem::TYPE,
                                    BinaryLogEntry::Elem::EVENT_TYPE_INT);
                        proto.write(BinaryLogEntry::Elem::VAL_INT32, (int)elem.data.int32);
                        break;
                    case EVENT_TYPE_LONG:
                        proto.write(BinaryLogEntry::Elem::TYPE,
                                    BinaryLogEntry::Elem::EVENT_TYPE_LONG);
                        proto.write(BinaryLogEntry::Elem::VAL_INT64, (long long)elem.data.int64);
                        break;
                    case EVENT_TYPE_STRING:
                        proto.write(BinaryLogEntry::Elem::TYPE,
                                    BinaryLogEntry::Elem::EVENT_TYPE_STRING);
                        proto.write(BinaryLogEntry::Elem::VAL_STRING, elem.data.string, elem.len);
                        break;
                    case EVENT_TYPE_FLOAT:
                        proto.write(BinaryLogEntry::Elem::TYPE,
                                    BinaryLogEntry::Elem::EVENT_TYPE_FLOAT);
                        proto.write(BinaryLogEntry::Elem::VAL_FLOAT, elem.data.float32);
                        break;
                    case EVENT_TYPE_LIST:
                        proto.write(BinaryLogEntry::Elem::TYPE,
                                    BinaryLogEntry::Elem::EVENT_TYPE_LIST);
                        break;
                    case EVENT_TYPE_LIST_STOP:
                        proto.write(BinaryLogEntry::Elem::TYPE,
                                    BinaryLogEntry::Elem::EVENT_TYPE_LIST_STOP);
                        break;
                    case EVENT_TYPE_UNKNOWN:
                        proto.write(BinaryLogEntry::Elem::TYPE,
                                    BinaryLogEntry::Elem::EVENT_TYPE_UNKNOWN);
                        break;
                }
                proto.end(elemToken);
            } while ((elem.type != EVENT_TYPE_UNKNOWN) && !elem.complete);
            proto.end(token);
            if (context) {
                android_log_destroy(&context);
            }
        } else {
            AndroidLogEntry entry;
            status = android_log_processLogBuffer(&msg.entry, &entry);
            if (status != OK) {
                ALOGW("[%s] fails to process to an entry.\n", this->name.string());
                err = status;
                break;
            }
            lastTimestamp.tv_sec = entry.tv_sec;
            lastTimestamp.tv_nsec = entry.tv_nsec;

            // format a TextLogEntry
            uint64_t token = proto.start(LogProto::TEXT_LOGS);
            proto.write(TextLogEntry::SEC, (long long)entry.tv_sec);
            proto.write(TextLogEntry::NANOSEC, (long long)entry.tv_nsec);
            proto.write(TextLogEntry::PRIORITY, (int)entry.priority);
            proto.write(TextLogEntry::UID, entry.uid);
            proto.write(TextLogEntry::PID, entry.pid);
            proto.write(TextLogEntry::TID, entry.tid);
            proto.write(TextLogEntry::TAG, entry.tag, trimTail(entry.tag, entry.tagLen));
            proto.write(TextLogEntry::LOG, entry.message,
                        trimTail(entry.message, entry.messageLen));
            proto.end(token);
        }
        if (!proto.flush(pipeWriteFd.get())) {
            if (errno == EPIPE) {
                ALOGW("[%s] wrote to a broken pipe\n", this->name.string());
            }
            err = errno;
            break;
        }
        proto.clear();
    }
    gLastLogsRetrieved[mLogID] = lastTimestamp;
    _exit(err);
}

// ================================================================================

const int LINK_NAME_LEN = 64;
const int EXE_NAME_LEN = 1024;

TombstoneSection::TombstoneSection(int id, const char* type, const int64_t timeoutMs)
    : WorkerThreadSection(id, timeoutMs), mType(type) {
    name = "tombstone ";
    name += type;
}

TombstoneSection::~TombstoneSection() {}

status_t TombstoneSection::BlockingCall(unique_fd& pipeWriteFd) const {
    std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
    if (proc.get() == nullptr) {
        ALOGE("opendir /proc failed: %s\n", strerror(errno));
        return -errno;
    }

    const std::set<int> hal_pids = get_interesting_hal_pids();

    auto pooledBuffer = get_buffer_from_pool();
    ProtoOutputStream proto(pooledBuffer);
    // dumpBufferSize should be a multiple of page size (4 KB) to reduce memory fragmentation
    size_t dumpBufferSize = 64 * 1024; // 64 KB is enough for most tombstone dump
    char* dumpBuffer = (char*)mmap(NULL, dumpBufferSize, PROT_READ | PROT_WRITE,
                MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
    struct dirent* d;
    char link_name[LINK_NAME_LEN];
    char exe_name[EXE_NAME_LEN];
    status_t err = NO_ERROR;
    while ((d = readdir(proc.get()))) {
        int pid = atoi(d->d_name);
        if (pid <= 0) {
            continue;
        }
        snprintf(link_name, LINK_NAME_LEN, "/proc/%d/exe", pid);
        struct stat fileStat;
        if (stat(link_name, &fileStat) != OK) {
            continue;
        }
        ssize_t exe_name_len = readlink(link_name, exe_name, EXE_NAME_LEN);
        if (exe_name_len < 0 || exe_name_len >= EXE_NAME_LEN) {
            ALOGE("[%s] Can't read '%s': %s", name.string(), link_name, strerror(errno));
            continue;
        }
        // readlink(2) does not put a null terminator at the end
        exe_name[exe_name_len] = '\0';

        bool is_java_process;
        if (strncmp(exe_name, "/system/bin/app_process32", LINK_NAME_LEN) == 0 ||
                strncmp(exe_name, "/system/bin/app_process64", LINK_NAME_LEN) == 0) {
            if (mType != "java") continue;
            // Don't bother dumping backtraces for the zygote.
            if (IsZygote(pid)) {
                VLOG("Skipping Zygote");
                continue;
            }

            is_java_process = true;
        } else if (should_dump_native_traces(exe_name)) {
            if (mType != "native") continue;
            is_java_process = false;
        } else if (hal_pids.find(pid) != hal_pids.end()) {
            if (mType != "hal") continue;
            is_java_process = false;
        } else {
            // Probably a native process we don't care about, continue.
            VLOG("Skipping %d", pid);
            continue;
        }

        Fpipe dumpPipe;
        if (!dumpPipe.init()) {
            ALOGW("[%s] failed to setup dump pipe", this->name.string());
            err = -errno;
            break;
        }

        const uint64_t start = Nanotime();
        pid_t child = fork();
        if (child < 0) {
            ALOGE("Failed to fork child process");
            break;
        } else if (child == 0) {
            // This is the child process.
            dumpPipe.readFd().reset();
            const int ret = dump_backtrace_to_file_timeout(
                    pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
                    is_java_process ? 5 : 20, dumpPipe.writeFd().get());
            if (ret == -1) {
                if (errno == 0) {
                    ALOGW("Dumping failed for pid '%d', likely due to a timeout\n", pid);
                } else {
                    ALOGE("Dumping failed for pid '%d': %s\n", pid, strerror(errno));
                }
            }
            dumpPipe.writeFd().reset();
            _exit(EXIT_SUCCESS);
        }
        dumpPipe.writeFd().reset();
        // Parent process.
        // Read from the pipe concurrently to avoid blocking the child.
        FdBuffer buffer;
        err = buffer.readFully(dumpPipe.readFd().get());
        // Wait on the child to avoid it becoming a zombie process.
        status_t cStatus = wait_child(child);
        if (err != NO_ERROR) {
            ALOGW("[%s] failed to read stack dump: %d", this->name.string(), err);
            dumpPipe.readFd().reset();
            break;
        }
        if (cStatus != NO_ERROR) {
            ALOGE("[%s] child had an issue: %s\n", this->name.string(), strerror(-cStatus));
        }

        // Resize dump buffer
        if (dumpBufferSize < buffer.size()) {
            munmap(dumpBuffer, dumpBufferSize);
            while(dumpBufferSize < buffer.size()) dumpBufferSize = dumpBufferSize << 1;
            dumpBuffer = (char*)mmap(NULL, dumpBufferSize, PROT_READ | PROT_WRITE,
                    MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
        }
        sp<ProtoReader> reader = buffer.data()->read();
        int i = 0;
        while (reader->hasNext()) {
            dumpBuffer[i] = reader->next();
            i++;
        }
        uint64_t token = proto.start(android::os::BackTraceProto::TRACES);
        proto.write(android::os::BackTraceProto::Stack::PID, pid);
        proto.write(android::os::BackTraceProto::Stack::DUMP, dumpBuffer, i);
        proto.write(android::os::BackTraceProto::Stack::DUMP_DURATION_NS,
                    static_cast<long long>(Nanotime() - start));
        proto.end(token);
        dumpPipe.readFd().reset();
        if (!proto.flush(pipeWriteFd.get())) {
            if (errno == EPIPE) {
                ALOGE("[%s] wrote to a broken pipe\n", this->name.string());
            }
            err = errno;
            break;
        }
        proto.clear();
    }
    munmap(dumpBuffer, dumpBufferSize);
    return_buffer_to_pool(pooledBuffer);
    return err;
}

// ================================================================================
BringYourOwnSection::BringYourOwnSection(int id, const char* customName, const uid_t callingUid,
        const sp<IIncidentDumpCallback>& callback)
    : WorkerThreadSection(id, REMOTE_CALL_TIMEOUT_MS), uid(callingUid), mCallback(callback) {
    name = "registered ";
    name += customName;
}

BringYourOwnSection::~BringYourOwnSection() {}

status_t BringYourOwnSection::BlockingCall(unique_fd& pipeWriteFd) const {
    android::os::ParcelFileDescriptor pfd(std::move(pipeWriteFd));
    if(mCallback != nullptr) {
        mCallback->onDumpSection(pfd);
    }
    return NO_ERROR;
}

}  // namespace incidentd
}  // namespace os
}  // namespace android
