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

Commit 44807bc8 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add metadata and headers to incident reports."

parents 9c1abe61 cbafce94
Loading
Loading
Loading
Loading
+13 −5
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@

#include <android/os/DropBoxManager.h>
#include <binder/IServiceManager.h>
#include <thread>

namespace android {
namespace os {
@@ -391,13 +392,20 @@ status_t Broadcaster::send_to_dropbox(const sp<ReportFile>& file,
        return NO_ERROR;
    }

    // Start a thread to write the data to dropbox.
    int readFd = -1;
    err = file->startFilteringData(&readFd, args);
    if (err != NO_ERROR) {
        return err;
    int fds[2];
    if (pipe(fds) != 0) {
        ALOGW("Error opening pipe to filter incident report: %s", file->getDataFileName().c_str());
        return NO_ERROR;
    }

    int readFd = fds[0];
    int writeFd = fds[1];

    // spawn a thread to write the data. Release the writeFd ownership to the thread.
    thread th([file, writeFd, args]() { file->startFilteringData(writeFd, args); });

    th.detach();

    // Takes ownership of readFd.
    Status status = dropbox->addFile(String16("incident"), readFd, 0);
    if (!status.isOk()) {
+14 −8
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <log/log.h>
#include <private/android_filesystem_config.h>
#include <utils/Looper.h>
#include <thread>

#include <unistd.h>

@@ -117,7 +118,8 @@ static Status checkIncidentPermissions(const IncidentReportArgs& args) {
}

static string build_uri(const string& pkg, const string& cls, const string& id) {
    return "build_uri not implemented " + pkg + "/" + cls + "/" + id;
    return "content://android.os.IncidentManager/pending?pkg="
        + pkg + "&receiver=" + cls + "&r=" + id;
}

// ================================================================================
@@ -358,17 +360,21 @@ Status IncidentService::getIncidentReport(const String16& pkg16, const String16&
    IncidentReportArgs args;
    sp<ReportFile> file = mWorkDirectory->getReport(pkg, cls, id, &args);
    if (file != nullptr) {
        int fd;
        err = file->startFilteringData(&fd, args);
        if (err != 0) {
            ALOGW("Error reading data file that we think should exist: %s",
        // Create pipe
        int fds[2];
        if (pipe(fds) != 0) {
            ALOGW("Error opening pipe to filter incident report: %s",
                  file->getDataFileName().c_str());
            return Status::ok();
        }

        result->setTimestampNs(file->getTimestampNs());
        result->setPrivacyPolicy(file->getEnvelope().privacy_policy());
        result->takeFileDescriptor(fd);
        result->takeFileDescriptor(fds[0]);
        int writeFd = fds[1];
        // spawn a thread to write the data. Release the writeFd ownership to the thread.
        thread th([file, writeFd, args]() { file->startFilteringData(writeFd, args); });

        th.detach();
    }

    return Status::ok();
+1 −1
Original line number Diff line number Diff line
@@ -551,7 +551,7 @@ void Reporter::runReport(size_t* reportByteSize) {
             buf++) {
            // If there was an error now, there will be an error later and we will remove
            // it from the list then.
            write_header_section(request->getFd(), *buf);
            write_header_section(request->getFd(), buf->data(), buf->size());
        }
    });

+30 −38
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include "WorkDirectory.h"

#include "proto_util.h"
#include "PrivacyFilter.h"

#include <google/protobuf/io/zero_copy_stream_impl.h>
@@ -64,6 +65,9 @@ static const string EXTENSION_DATA(".data");
 */
const ComponentName DROPBOX_SENTINEL("android", "DROPBOX");

/** metadata field id in IncidentProto */
const int FIELD_ID_INCIDENT_METADATA = 2;

/**
 * Read a protobuf from disk into the message.
 */
@@ -386,65 +390,53 @@ void ReportFile::closeDataFile() {
    }
}

status_t ReportFile::startFilteringData(int* fd, const IncidentReportArgs& args) {
status_t ReportFile::startFilteringData(int writeFd, const IncidentReportArgs& args) {
    // Open data file.
    int dataFd = open(mDataFileName.c_str(), O_RDONLY | O_CLOEXEC);
    if (dataFd < 0) {
        ALOGW("Error opening incident report '%s' %s", getDataFileName().c_str(), strerror(-errno));
        close(writeFd);
        return -errno;
    }

    // Check that the size on disk is what we thought we wrote.
    struct stat st;
    if (fstat(dataFd, &st) != 0) {
        ALOGW("Error running fstat incident report '%s' %s", getDataFileName().c_str(),
              strerror(-errno));
        close(writeFd);
        return -errno;
    }
    if (st.st_size != mEnvelope.data_file_size()) {
        ALOGW("File size mismatch. Envelope says %" PRIi64 " bytes but data file is %" PRIi64
                " bytes: %s", (int64_t)mEnvelope.data_file_size(), st.st_size,
                mDataFileName.c_str());
              " bytes: %s",
              (int64_t)mEnvelope.data_file_size(), st.st_size, mDataFileName.c_str());
        ALOGW("Removing incident report");
        mWorkDirectory->remove(this);
        close(writeFd);
        return BAD_VALUE;
    }

    // Create pipe
    int fds[2];
    if (pipe(fds) != 0) {
        ALOGW("Error opening pipe to filter incident report: %s", getDataFileName().c_str());
        return -errno;
    }
    status_t err;

    *fd = fds[0];
    int writeFd = fds[1];
    for (const auto& report : mEnvelope.report()) {
        for (const auto& header : report.header()) {
           write_header_section(writeFd,
               reinterpret_cast<const uint8_t*>(header.c_str()), header.size());
        }
    }

    // Spawn off a thread to do the filtering and writing
    thread th([this, dataFd, writeFd, args]() {
        ALOGD("worker thread started dataFd=%d writeFd=%d", dataFd, writeFd);
        status_t err;
    if (mEnvelope.has_metadata()) {
        write_section(writeFd, FIELD_ID_INCIDENT_METADATA, mEnvelope.metadata());
    }

    err = filter_and_write_report(writeFd, dataFd, mEnvelope.privacy_policy(), args);
        close(writeFd);

    if (err != NO_ERROR) {
        ALOGW("Error writing incident report '%s' to dropbox: %s", getDataFileName().c_str(),
                strerror(-err));
            // If there's an error here, there will also be an error returned from
            // addFile, so we'll use that error to reschedule the send_to_dropbox.
            // If the file is corrupted, we will put some logs in logcat, but won't
            // actually return an error.
            return;
    }
    });

    // Better would be to join this thread after write is back, but there is no
    // timeout parameter for that, which means we can't clean up if system server
    // is stuck. Better is to leak the thread, which will eventually clean itself
    // up after system server eventually dies, which it probably will.
    th.detach();

    // If the thread fails to start, we should return an error, but the thread
    // class doesn't give us a good way to determine that.  Just pretend everything
    // is ok.
    close(writeFd);
    return NO_ERROR;
}

+6 −6
Original line number Diff line number Diff line
@@ -135,14 +135,14 @@ public:
    void closeDataFile();

    /**
     * Spawn a thread to start writing and filtering data to a pipe, the read end of which
     * will be returned in fd.  This thread will be detached and run until somebody finishes
     * reading from the fd or closes it.  If there is an error, returns it and you will not
     * get an fd.
     * Use the privacy and section configuration from the args parameter to filter data, write
     * to [writeFd] and take the ownership of [writeFd].
     *
     * Use the privacy and section configuraiton from the args parameter.
     * Note: this call is blocking. When the writeFd is a pipe fd for IPC, caller should make sure
     * it's called on a separate thread so that reader can start to read without waiting for writer
     * to finish writing (which may not happen due to pipe buffer overflow).
     */
    status_t startFilteringData(int* fd, const IncidentReportArgs& args);
    status_t startFilteringData(int writeFd, const IncidentReportArgs& args);

    /**
     * Get the name of the data file on disk.
Loading