blob: 322b97293a263f964c4c37e995890d0ea60b2767 [file] [log] [blame]
Joe Onorato1754d742016-11-21 17:51:35 -08001/*
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 */
Yi Jin4e843102018-02-14 15:36:18 -080016#define DEBUG false
Yi Jinb592e3b2018-02-01 15:17:04 -080017#include "Log.h"
Joe Onorato1754d742016-11-21 17:51:35 -080018
19#include "Reporter.h"
Joe Onorato1754d742016-11-21 17:51:35 -080020
Joe Onorato99598ee2019-02-11 15:55:13 +000021#include "incidentd_util.h"
Yi Jin329130b2018-02-09 16:47:47 -080022#include "Privacy.h"
Joe Onorato99598ee2019-02-11 15:55:13 +000023#include "PrivacyFilter.h"
24#include "proto_util.h"
Joe Onorato1754d742016-11-21 17:51:35 -080025#include "report_directory.h"
26#include "section_list.h"
27
Joe Onorato99598ee2019-02-11 15:55:13 +000028#include <android-base/file.h>
Joe Onorato1754d742016-11-21 17:51:35 -080029#include <android/os/DropBoxManager.h>
Joe Onorato99598ee2019-02-11 15:55:13 +000030#include <android/util/protobuf.h>
31#include <android/util/ProtoOutputStream.h>
Yi Jin0a3406f2017-06-22 19:23:11 -070032#include <private/android_filesystem_config.h>
Joe Onorato1754d742016-11-21 17:51:35 -080033#include <utils/SystemClock.h>
34
Joe Onorato1754d742016-11-21 17:51:35 -080035#include <dirent.h>
Joe Onorato1754d742016-11-21 17:51:35 -080036#include <errno.h>
Yi Jinb592e3b2018-02-01 15:17:04 -080037#include <fcntl.h>
38#include <sys/stat.h>
39#include <sys/types.h>
Kweku Adams3d160912018-05-07 11:26:27 -070040#include <string>
Joe Onorato99598ee2019-02-11 15:55:13 +000041#include <time.h>
Joe Onorato1754d742016-11-21 17:51:35 -080042
Yi Jin6cacbcb2018-03-30 14:04:52 -070043namespace android {
44namespace os {
45namespace incidentd {
46
Joe Onorato99598ee2019-02-11 15:55:13 +000047using namespace android::util;
48
49/**
50 * The field id of the metadata section from
51 * frameworks/base/core/proto/android/os/incident.proto
52 */
53const int FIELD_ID_METADATA = 2;
54
55IncidentMetadata_Destination privacy_policy_to_dest(uint8_t privacyPolicy) {
56 switch (privacyPolicy) {
57 case PRIVACY_POLICY_AUTOMATIC:
58 return IncidentMetadata_Destination_AUTOMATIC;
59 case PRIVACY_POLICY_EXPLICIT:
60 return IncidentMetadata_Destination_EXPLICIT;
61 case PRIVACY_POLICY_LOCAL:
62 return IncidentMetadata_Destination_LOCAL;
63 default:
64 // Anything else reverts to automatic
65 return IncidentMetadata_Destination_AUTOMATIC;
66 }
67}
68
69void poo_make_metadata(IncidentMetadata* result, const IncidentMetadata& full,
70 int64_t reportId, int32_t privacyPolicy, const IncidentReportArgs& args) {
71 result->set_report_id(reportId);
72 result->set_dest(privacy_policy_to_dest(privacyPolicy));
73
74 size_t sectionCount = full.sections_size();
75 for (int sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++) {
76 const IncidentMetadata::SectionStats& sectionStats = full.sections(sectionIndex);
77 if (args.containsSection(sectionStats.id())) {
78 *result->add_sections() = sectionStats;
79 }
80 }
81}
82
83// ARGS must have a containsSection(int) method
84template <typename ARGS> void make_metadata(IncidentMetadata* result, const IncidentMetadata& full,
85 int64_t reportId, int32_t privacyPolicy, ARGS args) {
86 result->set_report_id(reportId);
87 result->set_dest(privacy_policy_to_dest(privacyPolicy));
88
89 size_t sectionCount = full.sections_size();
90 for (int sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++) {
91 const IncidentMetadata::SectionStats& sectionStats = full.sections(sectionIndex);
92 if (args->containsSection(sectionStats.id())) {
93 *result->add_sections() = sectionStats;
94 }
95 }
96}
97
98// ================================================================================
99class StreamingFilterFd : public FilterFd {
100public:
101 StreamingFilterFd(uint8_t privacyPolicy, int fd, const sp<ReportRequest>& request);
102
103 virtual void onWriteError(status_t err);
104
105private:
106 sp<ReportRequest> mRequest;
107};
108
109StreamingFilterFd::StreamingFilterFd(uint8_t privacyPolicy, int fd,
110 const sp<ReportRequest>& request)
111 :FilterFd(privacyPolicy, fd),
112 mRequest(request) {
113}
114
115void StreamingFilterFd::onWriteError(status_t err) {
116 mRequest->setStatus(err);
117}
118
119
120// ================================================================================
121class PersistedFilterFd : public FilterFd {
122public:
123 PersistedFilterFd(uint8_t privacyPolicy, int fd, const sp<ReportFile>& reportFile);
124
125 virtual void onWriteError(status_t err);
126
127private:
128 sp<ReportFile> mReportFile;
129};
130
131PersistedFilterFd::PersistedFilterFd(uint8_t privacyPolicy, int fd,
132 const sp<ReportFile>& reportFile)
133 :FilterFd(privacyPolicy, fd),
134 mReportFile(reportFile) {
135}
136
137void PersistedFilterFd::onWriteError(status_t err) {
138 mReportFile->setWriteError(err);
139}
140
141
Yi Jin0a3406f2017-06-22 19:23:11 -0700142// ================================================================================
Joe Onorato1754d742016-11-21 17:51:35 -0800143ReportRequest::ReportRequest(const IncidentReportArgs& a,
Joe Onorato99598ee2019-02-11 15:55:13 +0000144 const sp<IIncidentReportStatusListener>& listener, int fd)
145 :args(a),
146 mListener(listener),
147 mFd(fd),
148 mIsStreaming(fd >= 0),
149 mStatus(NO_ERROR) {
150}
Joe Onorato1754d742016-11-21 17:51:35 -0800151
Yi Jinb592e3b2018-02-01 15:17:04 -0800152ReportRequest::~ReportRequest() {
Joe Onorato99598ee2019-02-11 15:55:13 +0000153 if (mIsStreaming && mFd >= 0) {
Yi Jin22769e02017-10-16 14:42:50 -0700154 // clean up the opened file descriptor
Joe Onorato99598ee2019-02-11 15:55:13 +0000155 close(mFd);
Yi Jin22769e02017-10-16 14:42:50 -0700156 }
Joe Onorato1754d742016-11-21 17:51:35 -0800157}
158
Joe Onorato99598ee2019-02-11 15:55:13 +0000159bool ReportRequest::ok() {
160 return mFd >= 0 && mStatus == NO_ERROR;
Joe Onorato1754d742016-11-21 17:51:35 -0800161}
162
Joe Onorato99598ee2019-02-11 15:55:13 +0000163void ReportRequest::closeFd() {
164 if (mIsStreaming && mFd >= 0) {
165 close(mFd);
166 mFd = -1;
Yi Jin329130b2018-02-09 16:47:47 -0800167 }
Yi Jin3ec5cc72018-01-26 13:42:43 -0800168}
169
Joe Onorato1754d742016-11-21 17:51:35 -0800170// ================================================================================
Joe Onorato99598ee2019-02-11 15:55:13 +0000171ReportBatch::ReportBatch() {}
Yi Jinadd11e92017-07-30 16:10:07 -0700172
Joe Onorato99598ee2019-02-11 15:55:13 +0000173ReportBatch::~ReportBatch() {}
Joe Onorato1754d742016-11-21 17:51:35 -0800174
Joe Onorato99598ee2019-02-11 15:55:13 +0000175void ReportBatch::addPersistedReport(const IncidentReportArgs& args) {
176 ComponentName component(args.receiverPkg(), args.receiverCls());
177 map<ComponentName, sp<ReportRequest>>::iterator found = mPersistedRequests.find(component);
178 if (found == mPersistedRequests.end()) {
179 // not found
180 mPersistedRequests[component] = new ReportRequest(args, nullptr, -1);
181 } else {
182 // found
183 sp<ReportRequest> request = found->second;
184 request->args.merge(args);
185 }
Joe Onorato1754d742016-11-21 17:51:35 -0800186}
187
Joe Onorato99598ee2019-02-11 15:55:13 +0000188void ReportBatch::addStreamingReport(const IncidentReportArgs& args,
189 const sp<IIncidentReportStatusListener>& listener, int streamFd) {
190 mStreamingRequests.push_back(new ReportRequest(args, listener, streamFd));
191}
Joe Onorato1754d742016-11-21 17:51:35 -0800192
Joe Onorato99598ee2019-02-11 15:55:13 +0000193bool ReportBatch::empty() const {
194 return mPersistedRequests.size() == 0 && mStreamingRequests.size() == 0;
195}
196
197sp<ReportRequest> ReportBatch::getPersistedRequest(const ComponentName& component) {
198 map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.find(component);
199 if (it != mPersistedRequests.find(component)) {
200 return it->second;
201 } else {
202 return nullptr;
203 }
204}
205
206void ReportBatch::forEachPersistedRequest(const function<void (const sp<ReportRequest>&)>& func) {
207 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
208 it != mPersistedRequests.end(); it++) {
209 func(it->second);
210 }
211}
212
213void ReportBatch::forEachStreamingRequest(const function<void (const sp<ReportRequest>&)>& func) {
214 for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
215 request != mStreamingRequests.end(); request++) {
216 func(*request);
217 }
218}
219
220void ReportBatch::forEachListener(
221 const function<void (const sp<IIncidentReportStatusListener>&)>& func) {
222 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
223 it != mPersistedRequests.end(); it++) {
224 sp<IIncidentReportStatusListener> listener = it->second->getListener();
225 if (listener != nullptr) {
226 func(listener);
227 }
228 }
229 for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
230 request != mStreamingRequests.end(); request++) {
231 sp<IIncidentReportStatusListener> listener = (*request)->getListener();
232 if (listener != nullptr) {
233 func(listener);
234 }
235 }
236}
237
238void ReportBatch::forEachListener(int sectionId,
239 const function<void (const sp<IIncidentReportStatusListener>&)>& func) {
240 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
241 it != mPersistedRequests.end(); it++) {
242 if (it->second->containsSection(sectionId)) {
243 sp<IIncidentReportStatusListener> listener = it->second->getListener();
244 if (listener != nullptr) {
245 func(listener);
246 }
247 }
248 }
249 for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
250 request != mStreamingRequests.end(); request++) {
251 if ((*request)->containsSection(sectionId)) {
252 sp<IIncidentReportStatusListener> listener = (*request)->getListener();
253 if (listener != nullptr) {
254 func(listener);
255 }
256 }
257 }
258}
259
260void ReportBatch::getCombinedPersistedArgs(IncidentReportArgs* result) {
261 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
262 it != mPersistedRequests.end(); it++) {
263 result->merge(it->second->args);
264 }
265}
266
267bool ReportBatch::containsSection(int sectionId) {
268 // We don't cache this, because in case of error, we remove requests
269 // from the batch, and this is easier than recomputing the set.
270 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
271 it != mPersistedRequests.end(); it++) {
272 if (it->second->containsSection(sectionId)) {
273 return true;
274 }
275 }
276 for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
277 request != mStreamingRequests.end(); request++) {
278 if ((*request)->containsSection(sectionId)) {
279 return true;
280 }
281 }
282 return false;
283}
284
285void ReportBatch::clearPersistedRequests() {
286 mPersistedRequests.clear();
287}
288
289void ReportBatch::getFailedRequests(vector<sp<ReportRequest>>* requests) {
290 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
291 it != mPersistedRequests.end(); it++) {
292 if (it->second->getStatus() != NO_ERROR) {
293 requests->push_back(it->second);
294 }
295 }
296 for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
297 request != mStreamingRequests.end(); request++) {
298 if ((*request)->getStatus() != NO_ERROR) {
299 requests->push_back(*request);
300 }
301 }
302}
303
304void ReportBatch::removeRequest(const sp<ReportRequest>& request) {
305 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
306 it != mPersistedRequests.end(); it++) {
307 if (it->second == request) {
308 mPersistedRequests.erase(it);
309 return;
310 }
311 }
312 for (vector<sp<ReportRequest>>::iterator it = mStreamingRequests.begin();
313 it != mStreamingRequests.end(); it++) {
314 if (*it == request) {
315 mStreamingRequests.erase(it);
316 return;
317 }
318 }
319}
320
321// ================================================================================
322ReportWriter::ReportWriter(const sp<ReportBatch>& batch)
323 :mBatch(batch),
324 mPersistedFile(),
325 mMaxPersistedPrivacyPolicy(PRIVACY_POLICY_UNSET) {
326}
327
328ReportWriter::~ReportWriter() {
329}
330
331void ReportWriter::setPersistedFile(sp<ReportFile> file) {
332 mPersistedFile = file;
333}
334
335void ReportWriter::setMaxPersistedPrivacyPolicy(uint8_t privacyPolicy) {
336 mMaxPersistedPrivacyPolicy = privacyPolicy;
337}
338
339void ReportWriter::startSection(int sectionId) {
340 mCurrentSectionId = sectionId;
341 mSectionStartTimeMs = uptimeMillis();
342
343 mSectionStatsCalledForSectionId = -1;
344 mDumpSizeBytes = 0;
345 mDumpDurationMs = 0;
346 mSectionTimedOut = false;
347 mSectionTruncated = false;
348 mSectionBufferSuccess = false;
349 mHadError = false;
350 mSectionErrors.clear();
351
352}
353
354void ReportWriter::setSectionStats(const FdBuffer& buffer) {
355 mSectionStatsCalledForSectionId = mCurrentSectionId;
356 mDumpSizeBytes = buffer.size();
357 mDumpDurationMs = buffer.durationMs();
358 mSectionTimedOut = buffer.timedOut();
359 mSectionTruncated = buffer.truncated();
360 mSectionBufferSuccess = !buffer.timedOut() && !buffer.truncated();
361}
362
363void ReportWriter::endSection(IncidentMetadata::SectionStats* sectionMetadata) {
364 long endTime = uptimeMillis();
365
366 if (mSectionStatsCalledForSectionId != mCurrentSectionId) {
367 ALOGW("setSectionStats not called for section %d", mCurrentSectionId);
368 }
369
370 sectionMetadata->set_id(mCurrentSectionId);
371 sectionMetadata->set_success((!mHadError) && mSectionBufferSuccess);
372 sectionMetadata->set_report_size_bytes(mMaxSectionDataFilteredSize);
373 sectionMetadata->set_exec_duration_ms(endTime - mSectionStartTimeMs);
374 sectionMetadata->set_dump_size_bytes(mDumpSizeBytes);
375 sectionMetadata->set_dump_duration_ms(mDumpDurationMs);
376 sectionMetadata->set_timed_out(mSectionTimedOut);
377 sectionMetadata->set_is_truncated(mSectionTruncated);
378 sectionMetadata->set_error_msg(mSectionErrors);
379}
380
381void ReportWriter::warning(const Section* section, status_t err, const char* format, ...) {
382 va_list args;
383 va_start(args, format);
384 vflog(section, err, ANDROID_LOG_ERROR, "error", format, args);
385 va_end(args);
386}
387
388void ReportWriter::error(const Section* section, status_t err, const char* format, ...) {
389 va_list args;
390 va_start(args, format);
391 vflog(section, err, ANDROID_LOG_WARN, "warning", format, args);
392 va_end(args);
393}
394
395void ReportWriter::vflog(const Section* section, status_t err, int level, const char* levelText,
396 const char* format, va_list args) {
397 const char* prefixFormat = "%s in section %d (%d) '%s': ";
398 int prefixLen = snprintf(NULL, 0, prefixFormat, levelText, section->id,
399 err, strerror(-err));
400
401 va_list measureArgs;
402 va_copy(measureArgs, args);
403 int messageLen = vsnprintf(NULL, 0, format, args);
404 va_end(measureArgs);
405
406 char* line = (char*)malloc(prefixLen + messageLen + 1);
407 if (line == NULL) {
408 // All hope is lost, just give up.
409 return;
410 }
411
412 sprintf(line, prefixFormat, levelText, section->id, err, strerror(-err));
413
414 vsprintf(line + prefixLen, format, args);
415
416 __android_log_write(level, LOG_TAG, line);
417
418 if (mSectionErrors.length() == 0) {
419 mSectionErrors = line;
420 } else {
421 mSectionErrors += '\n';
422 mSectionErrors += line;
423 }
424
425 free(line);
426
427 if (level >= ANDROID_LOG_ERROR) {
428 mHadError = true;
429 }
430}
431
432// Reads data from FdBuffer and writes it to the requests file descriptor.
433status_t ReportWriter::writeSection(const FdBuffer& buffer) {
434 PrivacyFilter filter(mCurrentSectionId, get_privacy_of_section(mCurrentSectionId));
435
436 // Add the fd for the persisted requests
437 if (mPersistedFile != nullptr) {
438 filter.addFd(new PersistedFilterFd(mMaxPersistedPrivacyPolicy,
439 mPersistedFile->getDataFileFd(), mPersistedFile));
440 }
441
442 // Add the fds for the streamed requests
443 mBatch->forEachStreamingRequest([&filter, this](const sp<ReportRequest>& request) {
444 if (request->ok() && request->args.containsSection(mCurrentSectionId)) {
445 filter.addFd(new StreamingFilterFd(request->args.getPrivacyPolicy(),
446 request->getFd(), request));
447 }
448 });
449
Yao Chen43706b42019-04-21 14:34:30 -0700450 return filter.writeData(buffer, PRIVACY_POLICY_LOCAL, &mMaxSectionDataFilteredSize,
451 true /*encrypt if needed*/);
Joe Onorato99598ee2019-02-11 15:55:13 +0000452}
453
454
455// ================================================================================
456Reporter::Reporter(const sp<WorkDirectory>& workDirectory, const sp<ReportBatch>& batch)
457 :mWorkDirectory(workDirectory),
458 mWriter(batch),
459 mBatch(batch) {
460}
461
462Reporter::~Reporter() {
463}
464
465void Reporter::runReport(size_t* reportByteSize) {
Joe Onorato1754d742016-11-21 17:51:35 -0800466 status_t err = NO_ERROR;
Joe Onorato99598ee2019-02-11 15:55:13 +0000467
468 IncidentMetadata metadata;
469 int persistedPrivacyPolicy = PRIVACY_POLICY_UNSET;
Joe Onorato1754d742016-11-21 17:51:35 -0800470
Joe Onorato99598ee2019-02-11 15:55:13 +0000471 (*reportByteSize) = 0;
Joe Onorato1754d742016-11-21 17:51:35 -0800472
473 // Tell everyone that we're starting.
Joe Onorato99598ee2019-02-11 15:55:13 +0000474 ALOGI("Starting incident report");
475 mBatch->forEachListener([](const auto& listener) { listener->onReportStarted(); });
476
477 if (mBatch->hasPersistedReports()) {
478 // Open a work file to contain the contents of all of the persisted reports.
479 // For this block, if we can't initialize the report file for some reason,
480 // then we will remove the persisted ReportRequests from the report, but
481 // continue with the streaming ones.
482 mPersistedFile = mWorkDirectory->createReportFile();
483 ALOGI("Report will be persisted: envelope: %s data: %s",
484 mPersistedFile->getEnvelopeFileName().c_str(),
485 mPersistedFile->getDataFileName().c_str());
486
487 // Record all of the metadata to the persisted file's metadata file.
488 // It will be read from there and reconstructed as the actual reports
489 // are sent out.
490 if (mPersistedFile != nullptr) {
491 mBatch->forEachPersistedRequest([this, &persistedPrivacyPolicy](
492 const sp<ReportRequest>& request) {
493 mPersistedFile->addReport(request->args);
494 if (request->args.getPrivacyPolicy() < persistedPrivacyPolicy) {
495 persistedPrivacyPolicy = request->args.getPrivacyPolicy();
496 }
497 });
498 mPersistedFile->setMaxPersistedPrivacyPolicy(persistedPrivacyPolicy);
499 err = mPersistedFile->saveEnvelope();
500 if (err != NO_ERROR) {
501 mWorkDirectory->remove(mPersistedFile);
502 mPersistedFile = nullptr;
503 }
504 mWriter.setMaxPersistedPrivacyPolicy(persistedPrivacyPolicy);
505 }
506
507 if (mPersistedFile != nullptr) {
508 err = mPersistedFile->startWritingDataFile();
509 if (err != NO_ERROR) {
510 mWorkDirectory->remove(mPersistedFile);
511 mPersistedFile = nullptr;
512 }
513 }
514
515 if (mPersistedFile != nullptr) {
516 mWriter.setPersistedFile(mPersistedFile);
517 } else {
518 ALOGW("Error creating the persisted file, so clearing persisted reports.");
519 // If we couldn't open the file (permissions err, etc), then
520 // we still want to proceed with any streaming reports, but
521 // cancel all of the persisted ones.
522 mBatch->forEachPersistedRequest([](const sp<ReportRequest>& request) {
523 sp<IIncidentReportStatusListener> listener = request->getListener();
524 if (listener != nullptr) {
525 listener->onReportFailed();
526 }
527 });
528 mBatch->clearPersistedRequests();
Joe Onorato1754d742016-11-21 17:51:35 -0800529 }
530 }
531
Joe Onorato99598ee2019-02-11 15:55:13 +0000532 // If we have a persisted ID, then we allow all the readers to see that. There's
533 // enough in the data to allow for a join, and nothing in here that intrisincally
534 // could ever prevent that, so just give them the ID. If we don't have that then we
535 // make and ID that's extremely likely to be unique, but clock resetting could allow
536 // it to be duplicate.
537 int64_t reportId;
538 if (mPersistedFile != nullptr) {
539 reportId = mPersistedFile->getTimestampNs();
540 } else {
541 struct timespec spec;
542 clock_gettime(CLOCK_REALTIME, &spec);
543 reportId = (spec.tv_sec) * 1000 + spec.tv_nsec;
544 }
545
546 // Write the incident report headers - each request gets its own headers. It's different
547 // from the other top-level fields in IncidentReport that are the sections where the rest
548 // is all shared data (although with their own individual privacy filtering).
549 mBatch->forEachStreamingRequest([](const sp<ReportRequest>& request) {
550 const vector<vector<uint8_t>>& headers = request->args.headers();
551 for (vector<vector<uint8_t>>::const_iterator buf = headers.begin(); buf != headers.end();
552 buf++) {
553 // If there was an error now, there will be an error later and we will remove
554 // it from the list then.
Yao Chencbafce92019-04-01 15:56:44 -0700555 write_header_section(request->getFd(), buf->data(), buf->size());
Joe Onorato99598ee2019-02-11 15:55:13 +0000556 }
557 });
558
559 // If writing to any of the headers failed, we don't want to keep processing
560 // sections for it.
561 cancel_and_remove_failed_requests();
Joe Onorato1754d742016-11-21 17:51:35 -0800562
563 // For each of the report fields, see if we need it, and if so, execute the command
564 // and report to those that care that we're doing it.
Yi Jinb592e3b2018-02-01 15:17:04 -0800565 for (const Section** section = SECTION_LIST; *section; section++) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000566 const int sectionId = (*section)->id;
567
Joe Onorato99598ee2019-02-11 15:55:13 +0000568 // If nobody wants this section, skip it.
569 if (!mBatch->containsSection(sectionId)) {
570 continue;
Joe Onorato1754d742016-11-21 17:51:35 -0800571 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000572
573 ALOGD("Start incident report section %d '%s'", sectionId, (*section)->name.string());
574 IncidentMetadata::SectionStats* sectionMetadata = metadata.add_sections();
575
576 // Notify listener of starting
577 mBatch->forEachListener(sectionId, [sectionId](const auto& listener) {
578 listener->onReportSectionStatus(
579 sectionId, IIncidentReportStatusListener::STATUS_STARTING);
580 });
581
582 // Go get the data and write it into the file descriptors.
583 mWriter.startSection(sectionId);
584 err = (*section)->Execute(&mWriter);
585 mWriter.endSection(sectionMetadata);
586
587 // Sections returning errors are fatal. Most errors should not be fatal.
588 if (err != NO_ERROR) {
589 mWriter.error((*section), err, "Section failed. Stopping report.");
590 goto DONE;
591 }
592
593 // The returned max data size is used for throttling too many incident reports.
594 (*reportByteSize) += sectionMetadata->report_size_bytes();
595
596 // For any requests that failed during this section, remove them now. We do this
597 // before calling back about section finished, so listeners do not erroniously get the
598 // impression that the section succeeded. But we do it here instead of inside
599 // writeSection so that the callback is done from a known context and not from the
600 // bowels of a section, where changing the batch could cause odd errors.
601 cancel_and_remove_failed_requests();
602
603 // Notify listener of finishing
604 mBatch->forEachListener(sectionId, [sectionId](const auto& listener) {
605 listener->onReportSectionStatus(
606 sectionId, IIncidentReportStatusListener::STATUS_FINISHED);
607 });
608
609 ALOGD("Finish incident report section %d '%s'", sectionId, (*section)->name.string());
Joe Onorato1754d742016-11-21 17:51:35 -0800610 }
611
Yi Jinedfd5bb2017-09-06 17:09:11 -0700612DONE:
Joe Onorato99598ee2019-02-11 15:55:13 +0000613 // Finish up the persisted file.
614 if (mPersistedFile != nullptr) {
615 mPersistedFile->closeDataFile();
Yi Jin329130b2018-02-09 16:47:47 -0800616
Joe Onorato99598ee2019-02-11 15:55:13 +0000617 // Set the stored metadata
618 IncidentReportArgs combinedArgs;
619 mBatch->getCombinedPersistedArgs(&combinedArgs);
620 IncidentMetadata persistedMetadata;
621 make_metadata(&persistedMetadata, metadata, mPersistedFile->getTimestampNs(),
622 persistedPrivacyPolicy, &combinedArgs);
623 mPersistedFile->setMetadata(persistedMetadata);
Joe Onorato1754d742016-11-21 17:51:35 -0800624
Joe Onorato99598ee2019-02-11 15:55:13 +0000625 mPersistedFile->markCompleted();
626 err = mPersistedFile->saveEnvelope();
627 if (err != NO_ERROR) {
628 ALOGW("mPersistedFile->saveEnvelope returned %s. Won't send broadcast",
629 strerror(-err));
630 // Abandon ship.
631 mWorkDirectory->remove(mPersistedFile);
Joe Onorato1754d742016-11-21 17:51:35 -0800632 }
633 }
634
Joe Onorato99598ee2019-02-11 15:55:13 +0000635 // Write the metadata to the streaming ones
636 mBatch->forEachStreamingRequest([reportId, &metadata](const sp<ReportRequest>& request) {
637 IncidentMetadata streamingMetadata;
638 make_metadata(&streamingMetadata, metadata, reportId,
639 request->args.getPrivacyPolicy(), request);
640 status_t nonFatalErr = write_section(request->getFd(), FIELD_ID_METADATA,
641 streamingMetadata);
642 if (nonFatalErr != NO_ERROR) {
643 ALOGW("Error writing the metadata to streaming incident report. This is the last"
644 " thing so we won't return an error: %s", strerror(nonFatalErr));
Joe Onorato1754d742016-11-21 17:51:35 -0800645 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000646 });
Joe Onorato1754d742016-11-21 17:51:35 -0800647
Joe Onorato99598ee2019-02-11 15:55:13 +0000648 // Finish up the streaming ones.
649 mBatch->forEachStreamingRequest([](const sp<ReportRequest>& request) {
650 request->closeFd();
651 });
652
653 // Tell the listeners that we're done.
654 if (err == NO_ERROR) {
655 mBatch->forEachListener([](const auto& listener) {
656 listener->onReportFinished();
657 });
658 } else {
659 mBatch->forEachListener([](const auto& listener) {
660 listener->onReportFailed();
661 });
Joe Onorato1754d742016-11-21 17:51:35 -0800662 }
663
Joe Onorato99598ee2019-02-11 15:55:13 +0000664 ALOGI("Done taking incident report err=%s", strerror(-err));
Joe Onorato1754d742016-11-21 17:51:35 -0800665}
666
Joe Onorato99598ee2019-02-11 15:55:13 +0000667void Reporter::cancel_and_remove_failed_requests() {
668 // Handle a failure in the persisted file
669 if (mPersistedFile != nullptr) {
670 if (mPersistedFile->getWriteError() != NO_ERROR) {
671 ALOGW("Error writing to the persisted file (%s). Closing it and canceling.",
672 strerror(-mPersistedFile->getWriteError()));
673 mBatch->forEachPersistedRequest([this](const sp<ReportRequest>& request) {
674 sp<IIncidentReportStatusListener> listener = request->getListener();
675 if (listener != nullptr) {
676 listener->onReportFailed();
677 }
678 mBatch->removeRequest(request);
679 });
680 mWriter.setPersistedFile(nullptr);
681 mPersistedFile->closeDataFile();
682 mWorkDirectory->remove(mPersistedFile);
683 mPersistedFile = nullptr;
Joe Onorato1754d742016-11-21 17:51:35 -0800684 }
Joe Onorato1754d742016-11-21 17:51:35 -0800685 }
Joe Onorato1754d742016-11-21 17:51:35 -0800686
Joe Onorato99598ee2019-02-11 15:55:13 +0000687 // Handle failures in the streaming files
688 vector<sp<ReportRequest>> failed;
689 mBatch->getFailedRequests(&failed);
690 for (sp<ReportRequest>& request: failed) {
691 ALOGW("Error writing to a request stream (%s). Closing it and canceling.",
692 strerror(-request->getStatus()));
693 sp<IIncidentReportStatusListener> listener = request->getListener();
694 if (listener != nullptr) {
695 listener->onReportFailed();
696 }
697 request->closeFd(); // Will only close the streaming ones.
698 mBatch->removeRequest(request);
699 }
Joe Onorato1754d742016-11-21 17:51:35 -0800700}
Yi Jin6cacbcb2018-03-30 14:04:52 -0700701
702} // namespace incidentd
703} // namespace os
704} // namespace android