11754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato/*
21754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * Copyright (C) 2016 The Android Open Source Project
31754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato *
41754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * Licensed under the Apache License, Version 2.0 (the "License");
51754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * you may not use this file except in compliance with the License.
61754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * You may obtain a copy of the License at
71754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato *
81754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato *      http://www.apache.org/licenses/LICENSE-2.0
91754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato *
101754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * Unless required by applicable law or agreed to in writing, software
111754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * distributed under the License is distributed on an "AS IS" BASIS,
121754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * See the License for the specific language governing permissions and
141754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * limitations under the License.
151754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato */
161754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
171754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#define LOG_TAG "incidentd"
181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include "Reporter.h"
201754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include "protobuf.h"
211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include "report_directory.h"
231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include "section_list.h"
241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
251754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <private/android_filesystem_config.h>
261754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <android/os/DropBoxManager.h>
271754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <utils/SystemClock.h>
281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
291754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <sys/types.h>
301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <sys/stat.h>
311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <dirent.h>
321754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <fcntl.h>
331754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <errno.h>
341754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato/**
361754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * The directory where the incident reports are stored.
371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato */
381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatic const String8 INCIDENT_DIRECTORY("/data/incidents");
391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatic status_t
411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratowrite_all(int fd, uint8_t const* buf, size_t size)
421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    while (size > 0) {
441754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        ssize_t amt = ::write(fd, buf, size);
451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (amt < 0) {
461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return -errno;
471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        size -= amt;
491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        buf += amt;
501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    return NO_ERROR;
521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
531754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
541754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato// ================================================================================
551754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe OnoratoReportRequest::ReportRequest(const IncidentReportArgs& a,
561754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            const sp<IIncidentReportStatusListener> &l, int f)
571754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    :args(a),
581754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato     listener(l),
591754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato     fd(f),
601754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato     err(NO_ERROR)
611754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe OnoratoReportRequest::~ReportRequest()
651754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
671754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
681754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato// ================================================================================
691754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe OnoratoReportRequestSet::ReportRequestSet()
701754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    :mRequests(),
711754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato     mWritableCount(0),
721754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato     mMainFd(-1)
731754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
741754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
751754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
761754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe OnoratoReportRequestSet::~ReportRequestSet()
771754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
781754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
791754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
801754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratovoid
811754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe OnoratoReportRequestSet::add(const sp<ReportRequest>& request)
821754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
831754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    mRequests.push_back(request);
841754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    mWritableCount++;
851754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
861754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
871754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratovoid
881754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe OnoratoReportRequestSet::setMainFd(int fd)
891754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
901754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    mMainFd = fd;
911754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    mWritableCount++;
921754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
931754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
941754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatus_t
951754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe OnoratoReportRequestSet::write(uint8_t const* buf, size_t size)
961754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
971754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    status_t err = EBADF;
981754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
991754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    // The streaming ones
1001754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    int const N = mRequests.size();
1011754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    for (int i=N-1; i>=0; i--) {
1021754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        sp<ReportRequest> request = mRequests[i];
1031754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (request->fd >= 0 && request->err == NO_ERROR) {
1041754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            err = write_all(request->fd, buf, size);
1051754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (err != NO_ERROR) {
1061754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                request->err = err;
1071754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                mWritableCount--;
1081754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
1091754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
1101754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
1111754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1121754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    // The dropbox file
1131754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    if (mMainFd >= 0) {
1141754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        err = write_all(mMainFd, buf, size);
1151754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (err != NO_ERROR) {
1161754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            mMainFd = -1;
1171754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            mWritableCount--;
1181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
1191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
1201754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    // Return an error only when there are no FDs to write.
1221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    return mWritableCount > 0 ? NO_ERROR : err;
1231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
1241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1251754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1261754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato// ================================================================================
1271754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe OnoratoReporter::Reporter()
1281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    :args(),
1291754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato     batch()
1301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
1311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    char buf[100];
1321754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1331754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    // TODO: Make the max size smaller for user builds.
1341754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    mMaxSize = 100 * 1024 * 1024;
1351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    mMaxCount = 100;
1361754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    // There can't be two at the same time because it's on one thread.
1381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    mStartTime = time(NULL);
1391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    strftime(buf, sizeof(buf), "/incident-%Y%m%d-%H%M%S", localtime(&mStartTime));
1401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    mFilename = INCIDENT_DIRECTORY + buf;
1411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
1421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe OnoratoReporter::~Reporter()
1441754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
1451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
1461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe OnoratoReporter::run_report_status_t
1481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe OnoratoReporter::runReport()
1491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
1501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    status_t err = NO_ERROR;
1521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    bool needMainFd = false;
1531754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    int mainFd = -1;
1541754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1551754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    // See if we need the main file
1561754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
1571754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if ((*it)->fd < 0 && mainFd < 0) {
1581754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            needMainFd = true;
1591754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            break;
1601754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
1611754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
1621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    if (needMainFd) {
1631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        // Create the directory
1641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        err = create_directory(INCIDENT_DIRECTORY);
1651754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (err != NO_ERROR) {
1661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            goto done;
1671754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
1681754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1691754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        // If there are too many files in the directory (for whatever reason),
1701754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        // delete the oldest ones until it's under the limit. Doing this first
1711754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        // does mean that we can go over, so the max size is not a hard limit.
1721754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        clean_directory(INCIDENT_DIRECTORY, mMaxSize, mMaxCount);
1731754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1741754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        // Open the file.
1751754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        err = create_file(&mainFd);
1761754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (err != NO_ERROR) {
1771754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            goto done;
1781754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
1791754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1801754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        // Add to the set
1811754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        batch.setMainFd(mainFd);
1821754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
1831754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1841754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    // Tell everyone that we're starting.
1851754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
1861754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if ((*it)->listener != NULL) {
1871754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            (*it)->listener->onReportStarted();
1881754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
1891754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
1901754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1911754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    // Write the incident headers
1921754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
1931754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        const sp<ReportRequest> request = (*it);
1941754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        const vector<vector<int8_t>>& headers = request->args.headers();
1951754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1961754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        for (vector<vector<int8_t>>::const_iterator buf=headers.begin(); buf!=headers.end();
1971754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                buf++) {
1981754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            int fd = request->fd >= 0 ? request->fd : mainFd;
1991754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2001754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            uint8_t buffer[20];
2011754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            uint8_t* p = write_length_delimited_tag_header(buffer, FIELD_ID_INCIDENT_HEADER,
2021754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    buf->size());
2031754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            write_all(fd, buffer, p-buffer);
2041754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2051754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            write_all(fd, (uint8_t const*)buf->data(), buf->size());
2061754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // If there was an error now, there will be an error later and we will remove
2071754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // it from the list then.
2081754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
2091754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
2101754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2111754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    // For each of the report fields, see if we need it, and if so, execute the command
2121754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    // and report to those that care that we're doing it.
2131754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    for (const Section** section=SECTION_LIST; *section; section++) {
2141754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        const int id = (*section)->id;
2151754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        ALOGD("Taking incident report section %d '%s'", id, (*section)->name.string());
2161754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2171754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (this->args.containsSection(id)) {
2181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // Notify listener of starting
2191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
2201754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                if ((*it)->listener != NULL && (*it)->args.containsSection(id)) {
2211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    (*it)->listener->onReportSectionStatus(id,
2221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                            IIncidentReportStatusListener::STATUS_STARTING);
2231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                }
2241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
2251754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2261754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // Execute - go get the data and write it into the file descriptors.
2271754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            err = (*section)->Execute(&batch);
2281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (err != NO_ERROR) {
2291754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                ALOGW("Incident section %s (%d) failed. Stopping report.",
2301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                        (*section)->name.string(), id);
2311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                goto done;
2321754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
2331754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2341754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // Notify listener of starting
2351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
2361754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                if ((*it)->listener != NULL && (*it)->args.containsSection(id)) {
2371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    (*it)->listener->onReportSectionStatus(id,
2381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                            IIncidentReportStatusListener::STATUS_FINISHED);
2391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                }
2401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
2411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
2421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
2431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2441754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratodone:
2451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    // Close the file.
2461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    if (mainFd >= 0) {
2471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        close(mainFd);
2481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
2491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    // Tell everyone that we're done.
2511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
2521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if ((*it)->listener != NULL) {
2531754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (err == NO_ERROR) {
2541754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                (*it)->listener->onReportFinished();
2551754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            } else {
2561754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                (*it)->listener->onReportFailed();
2571754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
2581754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
2591754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
2601754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2611754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    // Put the report into dropbox.
2621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    if (needMainFd && err == NO_ERROR) {
2631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        sp<DropBoxManager> dropbox = new DropBoxManager();
2641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        Status status = dropbox->addFile(String16("incident"), mFilename, 0);
2651754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        ALOGD("Incident report done. dropbox status=%s\n", status.toString8().string());
2661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (!status.isOk()) {
2671754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return REPORT_NEEDS_DROPBOX;
2681754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
2691754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2701754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        // If the status was ok, delete the file. If not, leave it around until the next
2711754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        // boot or the next checkin. If the directory gets too big older files will
2721754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        // be rotated out.
2731754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        unlink(mFilename.c_str());
2741754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
2751754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2761754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    return REPORT_FINISHED;
2771754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
2781754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2791754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato/**
2801754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * Create our output file and set the access permissions to -rw-rw----
2811754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato */
2821754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatus_t
2831754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe OnoratoReporter::create_file(int* fd)
2841754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
2851754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    const char* filename = mFilename.c_str();
2861754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2871754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    *fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0660);
2881754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    if (*fd < 0) {
2891754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        ALOGE("Couldn't open incident file: %s (%s)", filename, strerror(errno));
2901754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        return -errno;
2911754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
2921754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2931754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    // Override umask. Not super critical. If it fails go on with life.
2941754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    chmod(filename, 0660);
2951754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
2961754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    if (chown(filename, AID_SYSTEM, AID_SYSTEM)) {
2971754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        ALOGE("Unable to change ownership of incident file %s: %s\n", filename, strerror(errno));
2981754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        status_t err = -errno;
2991754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        unlink(mFilename.c_str());
3001754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        return err;
3011754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
3021754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3031754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    return NO_ERROR;
3041754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
3051754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3061754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato// ================================================================================
3071754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe OnoratoReporter::run_report_status_t
3081754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe OnoratoReporter::upload_backlog()
3091754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{
3101754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    DIR* dir;
3111754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    struct dirent* entry;
3121754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    struct stat st;
3131754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3141754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    if ((dir = opendir(INCIDENT_DIRECTORY.string())) == NULL) {
3151754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        ALOGE("Couldn't open incident directory: %s", INCIDENT_DIRECTORY.string());
3161754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        return REPORT_NEEDS_DROPBOX;
3171754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
3181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    String8 dirbase(INCIDENT_DIRECTORY + "/");
3201754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    sp<DropBoxManager> dropbox = new DropBoxManager();
3211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    // Enumerate, count and add up size
3231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    while ((entry = readdir(dir)) != NULL) {
3241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (entry->d_name[0] == '.') {
3251754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            continue;
3261754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
3271754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        String8 filename = dirbase + entry->d_name;
3281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (stat(filename.string(), &st) != 0) {
3291754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            ALOGE("Unable to stat file %s", filename.string());
3301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            continue;
3311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
3321754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (!S_ISREG(st.st_mode)) {
3331754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            continue;
3341754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
3351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3361754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        Status status = dropbox->addFile(String16("incident"), filename.string(), 0);
3371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        ALOGD("Incident report done. dropbox status=%s\n", status.toString8().string());
3381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        if (!status.isOk()) {
3391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            return REPORT_NEEDS_DROPBOX;
3401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
3411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        // If the status was ok, delete the file. If not, leave it around until the next
3431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        // boot or the next checkin. If the directory gets too big older files will
3441754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        // be rotated out.
3451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        unlink(filename.string());
3461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
3471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    closedir(dir);
3491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
3501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    return REPORT_FINISHED;
3511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato}
3521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
353