• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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