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 
isStreaming()53     bool isStreaming() { return mIsStreaming; }
54 
setStatus(status_t err)55     void setStatus(status_t err) { mStatus = err; }
getStatus()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 
getListener()62     sp<IIncidentReportStatusListener> getListener() { return mListener; }
63 
getFd()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      */
hasPersistedReports()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