Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #pragma once
     17 
     18 #include "FdBuffer.h"
     19 #include "WorkDirectory.h"
     20 
     21 #include "frameworks/base/core/proto/android/os/metadata.pb.h"
     22 #include <android/content/ComponentName.h>
     23 #include <android/os/IIncidentReportStatusListener.h>
     24 #include <android/os/IncidentReportArgs.h>
     25 #include <android/util/protobuf.h>
     26 
     27 #include <map>
     28 #include <string>
     29 #include <vector>
     30 
     31 #include <time.h>
     32 #include <stdarg.h>
     33 
     34 namespace android {
     35 namespace os {
     36 namespace incidentd {
     37 
     38 using namespace std;
     39 using namespace android::content;
     40 using namespace android::os;
     41 
     42 class Section;
     43 
     44 // ================================================================================
     45 class ReportRequest : public virtual RefBase {
     46 public:
     47     IncidentReportArgs args;
     48 
     49     ReportRequest(const IncidentReportArgs& args, const sp<IIncidentReportStatusListener>& listener,
     50                   int fd);
     51     virtual ~ReportRequest();
     52 
     53     bool isStreaming() { return mIsStreaming; }
     54 
     55     void setStatus(status_t err) { mStatus = err; }
     56     status_t getStatus() const { return mStatus; }
     57 
     58     bool ok();  // returns true if the request is ok for write.
     59 
     60     bool containsSection(int sectionId) const;
     61 
     62     sp<IIncidentReportStatusListener> getListener() { return mListener; }
     63 
     64     int getFd() { return mFd; }
     65 
     66     int setPersistedFd(int fd);
     67 
     68     void closeFd();
     69 
     70 private:
     71     sp<IIncidentReportStatusListener> mListener;
     72     int mFd;
     73     bool mIsStreaming;
     74     status_t mStatus;
     75 };
     76 
     77 // ================================================================================
     78 class ReportBatch : public virtual RefBase {
     79 public:
     80     ReportBatch();
     81     virtual ~ReportBatch();
     82 
     83     // TODO: Should there be some kind of listener associated with the
     84     // component? Could be good for getting status updates e.g. in the ui,
     85     // as it progresses.  But that's out of scope for now.
     86 
     87     /**
     88      * Schedule a report for the "main" report, where it will be delivered to
     89      * the uploaders and/or dropbox.
     90      */
     91     void addPersistedReport(const IncidentReportArgs& args);
     92 
     93     /**
     94      * Adds a ReportRequest to the queue for one that has a listener an and fd
     95      */
     96     void addStreamingReport(const IncidentReportArgs& args,
     97            const sp<IIncidentReportStatusListener>& listener, int streamFd);
     98 
     99     /**
    100      * Returns whether both queues are empty.
    101      */
    102     bool empty() const;
    103 
    104     /**
    105      * Returns whether there are any persisted records.
    106      */
    107     bool hasPersistedReports() const { return mPersistedRequests.size() > 0; }
    108 
    109     /**
    110      * Return the persisted request for the given component, or nullptr.
    111      */
    112     sp<ReportRequest> getPersistedRequest(const ComponentName& component);
    113 
    114     /**
    115      * Call func(request) for each Request.
    116      */
    117     void forEachPersistedRequest(const function<void (const sp<ReportRequest>&)>& func);
    118 
    119     /**
    120      * Call func(request) for each Request.
    121      */
    122     void forEachStreamingRequest(const function<void (const sp<ReportRequest>&)>& func);
    123 
    124     /**
    125      * Call func(request) for each file descriptor that has
    126      */
    127     void forEachFd(int sectionId, const function<void (const sp<ReportRequest>&)>& func);
    128 
    129     /**
    130      * Call func(listener) for every listener in this batch.
    131      */
    132     void forEachListener(const function<void (const sp<IIncidentReportStatusListener>&)>& func);
    133 
    134     /**
    135      * Call func(listener) for every listener in this batch that requests
    136      * sectionId.
    137      */
    138     void forEachListener(int sectionId,
    139             const function<void (const sp<IIncidentReportStatusListener>&)>& func);
    140     /**
    141      * Get an IncidentReportArgs that represents the combined args for the
    142      * persisted requests.
    143      */
    144     void getCombinedPersistedArgs(IncidentReportArgs* results);
    145 
    146     /**
    147      * Return whether any of the requests contain the section.
    148      */
    149     bool containsSection(int id);
    150 
    151     /**
    152      * Remove all of the broadcast (persisted) requests.
    153      */
    154     void clearPersistedRequests();
    155 
    156     /**
    157      * Move the streaming requests in this batch to that batch.  After this call there
    158      * will be no streaming requests in this batch.
    159      */
    160     void transferStreamingRequests(const sp<ReportBatch>& that);
    161 
    162     /**
    163      * Move the persisted requests in this batch to that batch.  After this call there
    164      * will be no streaming requests in this batch.
    165      */
    166     void transferPersistedRequests(const sp<ReportBatch>& that);
    167 
    168     /**
    169      * Get the requests that have encountered errors.
    170      */
    171     void getFailedRequests(vector<sp<ReportRequest>>* requests);
    172 
    173     /**
    174      * Remove the request from whichever list it's in.
    175      */
    176     void removeRequest(const sp<ReportRequest>& request);
    177 
    178 
    179 private:
    180     map<ComponentName, sp<ReportRequest>> mPersistedRequests;
    181     vector<sp<ReportRequest>> mStreamingRequests;
    182 };
    183 
    184 // ================================================================================
    185 class ReportWriter {
    186 public:
    187     ReportWriter(const sp<ReportBatch>& batch);
    188     ~ReportWriter();
    189 
    190     void setPersistedFile(sp<ReportFile> file);
    191     void setMaxPersistedPrivacyPolicy(uint8_t privacyPolicy);
    192 
    193     void startSection(int sectionId);
    194     void endSection(IncidentMetadata::SectionStats* sectionStats);
    195 
    196     void setSectionStats(const FdBuffer& buffer);
    197 
    198     void warning(const Section* section, status_t err, const char* format, ...);
    199     void error(const Section* section, status_t err, const char* format, ...);
    200 
    201     status_t writeSection(const FdBuffer& buffer);
    202 
    203 private:
    204     // Data about all requests
    205     sp<ReportBatch> mBatch;
    206 
    207     /**
    208      * The file on disk where we will store the persisted file.
    209      */
    210     sp<ReportFile> mPersistedFile;
    211 
    212     /**
    213      * The least restricted privacy policy of all of the perstited
    214      * requests. We pre-filter to that to save disk space.
    215      */
    216     uint8_t mMaxPersistedPrivacyPolicy;
    217 
    218     /**
    219      * The current section that is being written.
    220      */
    221     int mCurrentSectionId;
    222 
    223     /**
    224      * The time that that the current section was started.
    225      */
    226     int64_t mSectionStartTimeMs;
    227 
    228     /**
    229      * The last section that setSectionStats was called for, so if someone misses
    230      * it we can log that.
    231      */
    232     int mSectionStatsCalledForSectionId;
    233 
    234     /*
    235      * Fields for IncidentMetadata.SectionStats.  Set by setSectionStats.  Accessed by
    236      * getSectionStats.
    237      */
    238     int32_t mDumpSizeBytes;
    239     int64_t mDumpDurationMs;
    240     bool mSectionTimedOut;
    241     bool mSectionTruncated;
    242     bool mSectionBufferSuccess;
    243     bool mHadError;
    244     string mSectionErrors;
    245     size_t mMaxSectionDataFilteredSize;
    246 
    247     void vflog(const Section* section, status_t err, int level, const char* levelText,
    248         const char* format, va_list args);
    249 };
    250 
    251 // ================================================================================
    252 class Reporter : public virtual RefBase {
    253 public:
    254     Reporter(const sp<WorkDirectory>& workDirectory, const sp<ReportBatch>& batch);
    255 
    256     virtual ~Reporter();
    257 
    258     // Run the report as described in the batch and args parameters.
    259     void runReport(size_t* reportByteSize);
    260 
    261 private:
    262     sp<WorkDirectory> mWorkDirectory;
    263     ReportWriter mWriter;
    264     sp<ReportBatch> mBatch;
    265     sp<ReportFile> mPersistedFile;
    266 
    267     void cancel_and_remove_failed_requests();
    268 };
    269 
    270 }  // namespace incidentd
    271 }  // namespace os
    272 }  // namespace android
    273