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 #define DEBUG false
17 #include "Log.h"
18
19 #include "Reporter.h"
20
21 #include "incidentd_util.h"
22 #include "Privacy.h"
23 #include "PrivacyFilter.h"
24 #include "proto_util.h"
25 #include "report_directory.h"
26 #include "section_list.h"
27
28 #include <android-base/file.h>
29 #include <android/os/DropBoxManager.h>
30 #include <android/util/protobuf.h>
31 #include <android/util/ProtoOutputStream.h>
32 #include <private/android_filesystem_config.h>
33 #include <utils/SystemClock.h>
34
35 #include <dirent.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <string>
41 #include <time.h>
42
43 namespace android {
44 namespace os {
45 namespace incidentd {
46
47 using namespace android::util;
48
49 /**
50 * The field id of the metadata section from
51 * frameworks/base/core/proto/android/os/incident.proto
52 */
53 const int FIELD_ID_METADATA = 2;
54
privacy_policy_to_dest(uint8_t privacyPolicy)55 IncidentMetadata_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
69
contains_section(const IncidentReportArgs & args,int sectionId)70 static bool contains_section(const IncidentReportArgs& args, int sectionId) {
71 return args.containsSection(sectionId, section_requires_specific_mention(sectionId));
72 }
73
contains_section(const sp<ReportRequest> & args,int sectionId)74 static bool contains_section(const sp<ReportRequest>& args, int sectionId) {
75 return args->containsSection(sectionId);
76 }
77
78 // ARGS must have a containsSection(int) method
79 template <typename ARGS>
make_metadata(IncidentMetadata * result,const IncidentMetadata & full,int64_t reportId,int32_t privacyPolicy,ARGS args)80 void make_metadata(IncidentMetadata* result, const IncidentMetadata& full,
81 int64_t reportId, int32_t privacyPolicy, ARGS args) {
82 result->set_report_id(reportId);
83 result->set_dest(privacy_policy_to_dest(privacyPolicy));
84
85 size_t sectionCount = full.sections_size();
86 for (int sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++) {
87 const IncidentMetadata::SectionStats& sectionStats = full.sections(sectionIndex);
88 if (contains_section(args, sectionStats.id())) {
89 *result->add_sections() = sectionStats;
90 }
91 }
92 }
93
94 // ================================================================================
95 class StreamingFilterFd : public FilterFd {
96 public:
97 StreamingFilterFd(uint8_t privacyPolicy, int fd, const sp<ReportRequest>& request);
98
99 virtual void onWriteError(status_t err);
100
101 private:
102 sp<ReportRequest> mRequest;
103 };
104
StreamingFilterFd(uint8_t privacyPolicy,int fd,const sp<ReportRequest> & request)105 StreamingFilterFd::StreamingFilterFd(uint8_t privacyPolicy, int fd,
106 const sp<ReportRequest>& request)
107 :FilterFd(privacyPolicy, fd),
108 mRequest(request) {
109 }
110
onWriteError(status_t err)111 void StreamingFilterFd::onWriteError(status_t err) {
112 mRequest->setStatus(err);
113 }
114
115
116 // ================================================================================
117 class PersistedFilterFd : public FilterFd {
118 public:
119 PersistedFilterFd(uint8_t privacyPolicy, int fd, const sp<ReportFile>& reportFile);
120
121 virtual void onWriteError(status_t err);
122
123 private:
124 sp<ReportFile> mReportFile;
125 };
126
PersistedFilterFd(uint8_t privacyPolicy,int fd,const sp<ReportFile> & reportFile)127 PersistedFilterFd::PersistedFilterFd(uint8_t privacyPolicy, int fd,
128 const sp<ReportFile>& reportFile)
129 :FilterFd(privacyPolicy, fd),
130 mReportFile(reportFile) {
131 }
132
onWriteError(status_t err)133 void PersistedFilterFd::onWriteError(status_t err) {
134 mReportFile->setWriteError(err);
135 }
136
137
138 // ================================================================================
ReportRequest(const IncidentReportArgs & a,const sp<IIncidentReportStatusListener> & listener,int fd)139 ReportRequest::ReportRequest(const IncidentReportArgs& a,
140 const sp<IIncidentReportStatusListener>& listener, int fd)
141 :args(a),
142 mListener(listener),
143 mFd(fd),
144 mIsStreaming(fd >= 0),
145 mStatus(NO_ERROR) {
146 }
147
~ReportRequest()148 ReportRequest::~ReportRequest() {
149 if (mIsStreaming && mFd >= 0) {
150 // clean up the opened file descriptor
151 close(mFd);
152 }
153 }
154
ok()155 bool ReportRequest::ok() {
156 return mFd >= 0 && mStatus == NO_ERROR;
157 }
158
containsSection(int sectionId) const159 bool ReportRequest::containsSection(int sectionId) const {
160 return args.containsSection(sectionId, section_requires_specific_mention(sectionId));
161 }
162
closeFd()163 void ReportRequest::closeFd() {
164 if (mIsStreaming && mFd >= 0) {
165 close(mFd);
166 mFd = -1;
167 }
168 }
169
170 // ================================================================================
ReportBatch()171 ReportBatch::ReportBatch() {}
172
~ReportBatch()173 ReportBatch::~ReportBatch() {}
174
addPersistedReport(const IncidentReportArgs & args)175 void 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 }
186 }
187
addStreamingReport(const IncidentReportArgs & args,const sp<IIncidentReportStatusListener> & listener,int streamFd)188 void ReportBatch::addStreamingReport(const IncidentReportArgs& args,
189 const sp<IIncidentReportStatusListener>& listener, int streamFd) {
190 mStreamingRequests.push_back(new ReportRequest(args, listener, streamFd));
191 }
192
empty() const193 bool ReportBatch::empty() const {
194 return mPersistedRequests.size() == 0 && mStreamingRequests.size() == 0;
195 }
196
getPersistedRequest(const ComponentName & component)197 sp<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
forEachPersistedRequest(const function<void (const sp<ReportRequest> &)> & func)206 void 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
forEachStreamingRequest(const function<void (const sp<ReportRequest> &)> & func)213 void 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
forEachListener(const function<void (const sp<IIncidentReportStatusListener> &)> & func)220 void 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
forEachListener(int sectionId,const function<void (const sp<IIncidentReportStatusListener> &)> & func)238 void 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
getCombinedPersistedArgs(IncidentReportArgs * result)260 void 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
containsSection(int sectionId)267 bool 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
clearPersistedRequests()285 void ReportBatch::clearPersistedRequests() {
286 mPersistedRequests.clear();
287 }
288
transferStreamingRequests(const sp<ReportBatch> & that)289 void ReportBatch::transferStreamingRequests(const sp<ReportBatch>& that) {
290 for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
291 request != mStreamingRequests.end(); request++) {
292 that->mStreamingRequests.push_back(*request);
293 }
294 mStreamingRequests.clear();
295 }
296
transferPersistedRequests(const sp<ReportBatch> & that)297 void ReportBatch::transferPersistedRequests(const sp<ReportBatch>& that) {
298 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
299 it != mPersistedRequests.end(); it++) {
300 that->mPersistedRequests[it->first] = it->second;
301 }
302 mPersistedRequests.clear();
303 }
304
getFailedRequests(vector<sp<ReportRequest>> * requests)305 void ReportBatch::getFailedRequests(vector<sp<ReportRequest>>* requests) {
306 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
307 it != mPersistedRequests.end(); it++) {
308 if (it->second->getStatus() != NO_ERROR) {
309 requests->push_back(it->second);
310 }
311 }
312 for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
313 request != mStreamingRequests.end(); request++) {
314 if ((*request)->getStatus() != NO_ERROR) {
315 requests->push_back(*request);
316 }
317 }
318 }
319
removeRequest(const sp<ReportRequest> & request)320 void ReportBatch::removeRequest(const sp<ReportRequest>& request) {
321 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
322 it != mPersistedRequests.end(); it++) {
323 if (it->second == request) {
324 mPersistedRequests.erase(it);
325 return;
326 }
327 }
328 for (vector<sp<ReportRequest>>::iterator it = mStreamingRequests.begin();
329 it != mStreamingRequests.end(); it++) {
330 if (*it == request) {
331 mStreamingRequests.erase(it);
332 return;
333 }
334 }
335 }
336
337 // ================================================================================
ReportWriter(const sp<ReportBatch> & batch)338 ReportWriter::ReportWriter(const sp<ReportBatch>& batch)
339 :mBatch(batch),
340 mPersistedFile(),
341 mMaxPersistedPrivacyPolicy(PRIVACY_POLICY_UNSET) {
342 }
343
~ReportWriter()344 ReportWriter::~ReportWriter() {
345 }
346
setPersistedFile(sp<ReportFile> file)347 void ReportWriter::setPersistedFile(sp<ReportFile> file) {
348 mPersistedFile = file;
349 }
350
setMaxPersistedPrivacyPolicy(uint8_t privacyPolicy)351 void ReportWriter::setMaxPersistedPrivacyPolicy(uint8_t privacyPolicy) {
352 mMaxPersistedPrivacyPolicy = privacyPolicy;
353 }
354
startSection(int sectionId)355 void ReportWriter::startSection(int sectionId) {
356 mCurrentSectionId = sectionId;
357 mSectionStartTimeMs = uptimeMillis();
358
359 mSectionStatsCalledForSectionId = -1;
360 mDumpSizeBytes = 0;
361 mDumpDurationMs = 0;
362 mSectionTimedOut = false;
363 mSectionTruncated = false;
364 mSectionBufferSuccess = false;
365 mHadError = false;
366 mSectionErrors.clear();
367
368 }
369
setSectionStats(const FdBuffer & buffer)370 void ReportWriter::setSectionStats(const FdBuffer& buffer) {
371 mSectionStatsCalledForSectionId = mCurrentSectionId;
372 mDumpSizeBytes = buffer.size();
373 mDumpDurationMs = buffer.durationMs();
374 mSectionTimedOut = buffer.timedOut();
375 mSectionTruncated = buffer.truncated();
376 mSectionBufferSuccess = !buffer.timedOut() && !buffer.truncated();
377 }
378
endSection(IncidentMetadata::SectionStats * sectionMetadata)379 void ReportWriter::endSection(IncidentMetadata::SectionStats* sectionMetadata) {
380 long endTime = uptimeMillis();
381
382 if (mSectionStatsCalledForSectionId != mCurrentSectionId) {
383 ALOGW("setSectionStats not called for section %d", mCurrentSectionId);
384 }
385
386 sectionMetadata->set_id(mCurrentSectionId);
387 sectionMetadata->set_success((!mHadError) && mSectionBufferSuccess);
388 sectionMetadata->set_report_size_bytes(mMaxSectionDataFilteredSize);
389 sectionMetadata->set_exec_duration_ms(endTime - mSectionStartTimeMs);
390 sectionMetadata->set_dump_size_bytes(mDumpSizeBytes);
391 sectionMetadata->set_dump_duration_ms(mDumpDurationMs);
392 sectionMetadata->set_timed_out(mSectionTimedOut);
393 sectionMetadata->set_is_truncated(mSectionTruncated);
394 sectionMetadata->set_error_msg(mSectionErrors);
395 }
396
warning(const Section * section,status_t err,const char * format,...)397 void ReportWriter::warning(const Section* section, status_t err, const char* format, ...) {
398 va_list args;
399 va_start(args, format);
400 vflog(section, err, ANDROID_LOG_ERROR, "error", format, args);
401 va_end(args);
402 }
403
error(const Section * section,status_t err,const char * format,...)404 void ReportWriter::error(const Section* section, status_t err, const char* format, ...) {
405 va_list args;
406 va_start(args, format);
407 vflog(section, err, ANDROID_LOG_WARN, "warning", format, args);
408 va_end(args);
409 }
410
vflog(const Section * section,status_t err,int level,const char * levelText,const char * format,va_list args)411 void ReportWriter::vflog(const Section* section, status_t err, int level, const char* levelText,
412 const char* format, va_list args) {
413 const char* prefixFormat = "%s in section %d (%d) '%s': ";
414 int prefixLen = snprintf(NULL, 0, prefixFormat, levelText, section->id,
415 err, strerror(-err));
416
417 va_list measureArgs;
418 va_copy(measureArgs, args);
419 int messageLen = vsnprintf(NULL, 0, format, args);
420 va_end(measureArgs);
421
422 char* line = (char*)malloc(prefixLen + messageLen + 1);
423 if (line == NULL) {
424 // All hope is lost, just give up.
425 return;
426 }
427
428 sprintf(line, prefixFormat, levelText, section->id, err, strerror(-err));
429
430 vsprintf(line + prefixLen, format, args);
431
432 __android_log_write(level, LOG_TAG, line);
433
434 if (mSectionErrors.length() == 0) {
435 mSectionErrors = line;
436 } else {
437 mSectionErrors += '\n';
438 mSectionErrors += line;
439 }
440
441 free(line);
442
443 if (level >= ANDROID_LOG_ERROR) {
444 mHadError = true;
445 }
446 }
447
448 // Reads data from FdBuffer and writes it to the requests file descriptor.
writeSection(const FdBuffer & buffer)449 status_t ReportWriter::writeSection(const FdBuffer& buffer) {
450 PrivacyFilter filter(mCurrentSectionId, get_privacy_of_section(mCurrentSectionId));
451
452 // Add the fd for the persisted requests
453 if (mPersistedFile != nullptr) {
454 filter.addFd(new PersistedFilterFd(mMaxPersistedPrivacyPolicy,
455 mPersistedFile->getDataFileFd(), mPersistedFile));
456 }
457
458 // Add the fds for the streamed requests
459 mBatch->forEachStreamingRequest([&filter, this](const sp<ReportRequest>& request) {
460 if (request->ok()
461 && request->args.containsSection(mCurrentSectionId,
462 section_requires_specific_mention(mCurrentSectionId))) {
463 filter.addFd(new StreamingFilterFd(request->args.getPrivacyPolicy(),
464 request->getFd(), request));
465 }
466 });
467
468 return filter.writeData(buffer, PRIVACY_POLICY_LOCAL, &mMaxSectionDataFilteredSize);
469 }
470
471
472 // ================================================================================
Reporter(const sp<WorkDirectory> & workDirectory,const sp<ReportBatch> & batch)473 Reporter::Reporter(const sp<WorkDirectory>& workDirectory, const sp<ReportBatch>& batch)
474 :mWorkDirectory(workDirectory),
475 mWriter(batch),
476 mBatch(batch) {
477 }
478
~Reporter()479 Reporter::~Reporter() {
480 }
481
runReport(size_t * reportByteSize)482 void Reporter::runReport(size_t* reportByteSize) {
483 status_t err = NO_ERROR;
484
485 IncidentMetadata metadata;
486 int persistedPrivacyPolicy = PRIVACY_POLICY_UNSET;
487
488 (*reportByteSize) = 0;
489
490 // Tell everyone that we're starting.
491 ALOGI("Starting incident report");
492 mBatch->forEachListener([](const auto& listener) { listener->onReportStarted(); });
493
494 if (mBatch->hasPersistedReports()) {
495 // Open a work file to contain the contents of all of the persisted reports.
496 // For this block, if we can't initialize the report file for some reason,
497 // then we will remove the persisted ReportRequests from the report, but
498 // continue with the streaming ones.
499 mPersistedFile = mWorkDirectory->createReportFile();
500 ALOGI("Report will be persisted: envelope: %s data: %s",
501 mPersistedFile->getEnvelopeFileName().c_str(),
502 mPersistedFile->getDataFileName().c_str());
503
504 // Record all of the metadata to the persisted file's metadata file.
505 // It will be read from there and reconstructed as the actual reports
506 // are sent out.
507 if (mPersistedFile != nullptr) {
508 mBatch->forEachPersistedRequest([this, &persistedPrivacyPolicy](
509 const sp<ReportRequest>& request) {
510 mPersistedFile->addReport(request->args);
511 if (request->args.getPrivacyPolicy() < persistedPrivacyPolicy) {
512 persistedPrivacyPolicy = request->args.getPrivacyPolicy();
513 }
514 });
515 mPersistedFile->setMaxPersistedPrivacyPolicy(persistedPrivacyPolicy);
516 err = mPersistedFile->saveEnvelope();
517 if (err != NO_ERROR) {
518 mWorkDirectory->remove(mPersistedFile);
519 mPersistedFile = nullptr;
520 }
521 mWriter.setMaxPersistedPrivacyPolicy(persistedPrivacyPolicy);
522 }
523
524 if (mPersistedFile != nullptr) {
525 err = mPersistedFile->startWritingDataFile();
526 if (err != NO_ERROR) {
527 mWorkDirectory->remove(mPersistedFile);
528 mPersistedFile = nullptr;
529 }
530 }
531
532 if (mPersistedFile != nullptr) {
533 mWriter.setPersistedFile(mPersistedFile);
534 } else {
535 ALOGW("Error creating the persisted file, so clearing persisted reports.");
536 // If we couldn't open the file (permissions err, etc), then
537 // we still want to proceed with any streaming reports, but
538 // cancel all of the persisted ones.
539 mBatch->forEachPersistedRequest([](const sp<ReportRequest>& request) {
540 sp<IIncidentReportStatusListener> listener = request->getListener();
541 if (listener != nullptr) {
542 listener->onReportFailed();
543 }
544 });
545 mBatch->clearPersistedRequests();
546 }
547 }
548
549 // If we have a persisted ID, then we allow all the readers to see that. There's
550 // enough in the data to allow for a join, and nothing in here that intrisincally
551 // could ever prevent that, so just give them the ID. If we don't have that then we
552 // make and ID that's extremely likely to be unique, but clock resetting could allow
553 // it to be duplicate.
554 int64_t reportId;
555 if (mPersistedFile != nullptr) {
556 reportId = mPersistedFile->getTimestampNs();
557 } else {
558 struct timespec spec;
559 clock_gettime(CLOCK_REALTIME, &spec);
560 reportId = (spec.tv_sec) * 1000 + spec.tv_nsec;
561 }
562
563 // Write the incident report headers - each request gets its own headers. It's different
564 // from the other top-level fields in IncidentReport that are the sections where the rest
565 // is all shared data (although with their own individual privacy filtering).
566 mBatch->forEachStreamingRequest([](const sp<ReportRequest>& request) {
567 const vector<vector<uint8_t>>& headers = request->args.headers();
568 for (vector<vector<uint8_t>>::const_iterator buf = headers.begin(); buf != headers.end();
569 buf++) {
570 // If there was an error now, there will be an error later and we will remove
571 // it from the list then.
572 write_header_section(request->getFd(), buf->data(), buf->size());
573 }
574 });
575
576 // If writing to any of the headers failed, we don't want to keep processing
577 // sections for it.
578 cancel_and_remove_failed_requests();
579
580 // For each of the report fields, see if we need it, and if so, execute the command
581 // and report to those that care that we're doing it.
582 for (const Section** section = SECTION_LIST; *section; section++) {
583 const int sectionId = (*section)->id;
584
585 // If nobody wants this section, skip it.
586 if (!mBatch->containsSection(sectionId)) {
587 continue;
588 }
589
590 ALOGD("Start incident report section %d '%s'", sectionId, (*section)->name.string());
591 IncidentMetadata::SectionStats* sectionMetadata = metadata.add_sections();
592
593 // Notify listener of starting
594 mBatch->forEachListener(sectionId, [sectionId](const auto& listener) {
595 listener->onReportSectionStatus(
596 sectionId, IIncidentReportStatusListener::STATUS_STARTING);
597 });
598
599 // Go get the data and write it into the file descriptors.
600 mWriter.startSection(sectionId);
601 err = (*section)->Execute(&mWriter);
602 mWriter.endSection(sectionMetadata);
603
604 // Sections returning errors are fatal. Most errors should not be fatal.
605 if (err != NO_ERROR) {
606 mWriter.error((*section), err, "Section failed. Stopping report.");
607 goto DONE;
608 }
609
610 // The returned max data size is used for throttling too many incident reports.
611 (*reportByteSize) += sectionMetadata->report_size_bytes();
612
613 // For any requests that failed during this section, remove them now. We do this
614 // before calling back about section finished, so listeners do not erroniously get the
615 // impression that the section succeeded. But we do it here instead of inside
616 // writeSection so that the callback is done from a known context and not from the
617 // bowels of a section, where changing the batch could cause odd errors.
618 cancel_and_remove_failed_requests();
619
620 // Notify listener of finishing
621 mBatch->forEachListener(sectionId, [sectionId](const auto& listener) {
622 listener->onReportSectionStatus(
623 sectionId, IIncidentReportStatusListener::STATUS_FINISHED);
624 });
625
626 ALOGD("Finish incident report section %d '%s'", sectionId, (*section)->name.string());
627 }
628
629 DONE:
630 // Finish up the persisted file.
631 if (mPersistedFile != nullptr) {
632 mPersistedFile->closeDataFile();
633
634 // Set the stored metadata
635 IncidentReportArgs combinedArgs;
636 mBatch->getCombinedPersistedArgs(&combinedArgs);
637 IncidentMetadata persistedMetadata;
638 make_metadata(&persistedMetadata, metadata, mPersistedFile->getTimestampNs(),
639 persistedPrivacyPolicy, combinedArgs);
640 mPersistedFile->setMetadata(persistedMetadata);
641
642 mPersistedFile->markCompleted();
643 err = mPersistedFile->saveEnvelope();
644 if (err != NO_ERROR) {
645 ALOGW("mPersistedFile->saveEnvelope returned %s. Won't send broadcast",
646 strerror(-err));
647 // Abandon ship.
648 mWorkDirectory->remove(mPersistedFile);
649 }
650 }
651
652 // Write the metadata to the streaming ones
653 mBatch->forEachStreamingRequest([reportId, &metadata](const sp<ReportRequest>& request) {
654 IncidentMetadata streamingMetadata;
655 make_metadata(&streamingMetadata, metadata, reportId,
656 request->args.getPrivacyPolicy(), request);
657 status_t nonFatalErr = write_section(request->getFd(), FIELD_ID_METADATA,
658 streamingMetadata);
659 if (nonFatalErr != NO_ERROR) {
660 ALOGW("Error writing the metadata to streaming incident report. This is the last"
661 " thing so we won't return an error: %s", strerror(nonFatalErr));
662 }
663 });
664
665 // Finish up the streaming ones.
666 mBatch->forEachStreamingRequest([](const sp<ReportRequest>& request) {
667 request->closeFd();
668 });
669
670 // Tell the listeners that we're done.
671 if (err == NO_ERROR) {
672 mBatch->forEachListener([](const auto& listener) {
673 listener->onReportFinished();
674 });
675 } else {
676 mBatch->forEachListener([](const auto& listener) {
677 listener->onReportFailed();
678 });
679 }
680
681 ALOGI("Done taking incident report err=%s", strerror(-err));
682 }
683
cancel_and_remove_failed_requests()684 void Reporter::cancel_and_remove_failed_requests() {
685 // Handle a failure in the persisted file
686 if (mPersistedFile != nullptr) {
687 if (mPersistedFile->getWriteError() != NO_ERROR) {
688 ALOGW("Error writing to the persisted file (%s). Closing it and canceling.",
689 strerror(-mPersistedFile->getWriteError()));
690 mBatch->forEachPersistedRequest([this](const sp<ReportRequest>& request) {
691 sp<IIncidentReportStatusListener> listener = request->getListener();
692 if (listener != nullptr) {
693 listener->onReportFailed();
694 }
695 mBatch->removeRequest(request);
696 });
697 mWriter.setPersistedFile(nullptr);
698 mPersistedFile->closeDataFile();
699 mWorkDirectory->remove(mPersistedFile);
700 mPersistedFile = nullptr;
701 }
702 }
703
704 // Handle failures in the streaming files
705 vector<sp<ReportRequest>> failed;
706 mBatch->getFailedRequests(&failed);
707 for (sp<ReportRequest>& request: failed) {
708 ALOGW("Error writing to a request stream (%s). Closing it and canceling.",
709 strerror(-request->getStatus()));
710 sp<IIncidentReportStatusListener> listener = request->getListener();
711 if (listener != nullptr) {
712 listener->onReportFailed();
713 }
714 request->closeFd(); // Will only close the streaming ones.
715 mBatch->removeRequest(request);
716 }
717 }
718
719 } // namespace incidentd
720 } // namespace os
721 } // namespace android
722