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