• 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/prctl.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <string>
42 #include <time.h>
43 #include <wait.h>
44 
45 namespace android {
46 namespace os {
47 namespace incidentd {
48 
49 using namespace android::util;
50 
51 /**
52  * The field id of the metadata section from
53  *      frameworks/base/core/proto/android/os/incident.proto
54  */
55 const int FIELD_ID_METADATA = 2;
56 // Args for exec gzip
57 static const char* GZIP[] = {"/system/bin/gzip", NULL};
58 
privacy_policy_to_dest(uint8_t privacyPolicy)59 IncidentMetadata_Destination privacy_policy_to_dest(uint8_t privacyPolicy) {
60     switch (privacyPolicy) {
61         case PRIVACY_POLICY_AUTOMATIC:
62             return IncidentMetadata_Destination_AUTOMATIC;
63         case PRIVACY_POLICY_EXPLICIT:
64             return IncidentMetadata_Destination_EXPLICIT;
65         case PRIVACY_POLICY_LOCAL:
66             return IncidentMetadata_Destination_LOCAL;
67         default:
68             // Anything else reverts to automatic
69             return IncidentMetadata_Destination_AUTOMATIC;
70     }
71 }
72 
73 
contains_section(const IncidentReportArgs & args,int sectionId)74 static bool contains_section(const IncidentReportArgs& args, int sectionId) {
75     return args.containsSection(sectionId, section_requires_specific_mention(sectionId));
76 }
77 
contains_section(const sp<ReportRequest> & args,int sectionId)78 static bool contains_section(const sp<ReportRequest>& args, int sectionId) {
79     return args->containsSection(sectionId);
80 }
81 
82 // ARGS must have a containsSection(int) method
83 template <typename ARGS>
make_metadata(IncidentMetadata * result,const IncidentMetadata & full,int64_t reportId,int32_t privacyPolicy,ARGS args)84 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 (contains_section(args, sectionStats.id())) {
93             *result->add_sections() = sectionStats;
94         }
95     }
96 }
97 
98 // ================================================================================
99 class StreamingFilterFd : public FilterFd {
100 public:
101     StreamingFilterFd(uint8_t privacyPolicy, int fd, const sp<ReportRequest>& request);
102 
103     virtual void onWriteError(status_t err);
104 
105 private:
106     sp<ReportRequest> mRequest;
107 };
108 
StreamingFilterFd(uint8_t privacyPolicy,int fd,const sp<ReportRequest> & request)109 StreamingFilterFd::StreamingFilterFd(uint8_t privacyPolicy, int fd,
110             const sp<ReportRequest>& request)
111         :FilterFd(privacyPolicy, fd),
112          mRequest(request) {
113 }
114 
onWriteError(status_t err)115 void StreamingFilterFd::onWriteError(status_t err) {
116     mRequest->setStatus(err);
117 }
118 
119 
120 // ================================================================================
121 class PersistedFilterFd : public FilterFd {
122 public:
123     PersistedFilterFd(uint8_t privacyPolicy, int fd, const sp<ReportFile>& reportFile);
124 
125     virtual void onWriteError(status_t err);
126 
127 private:
128     sp<ReportFile> mReportFile;
129 };
130 
PersistedFilterFd(uint8_t privacyPolicy,int fd,const sp<ReportFile> & reportFile)131 PersistedFilterFd::PersistedFilterFd(uint8_t privacyPolicy, int fd,
132             const sp<ReportFile>& reportFile)
133         :FilterFd(privacyPolicy, fd),
134          mReportFile(reportFile) {
135 }
136 
onWriteError(status_t err)137 void PersistedFilterFd::onWriteError(status_t err) {
138     mReportFile->setWriteError(err);
139 }
140 
141 
142 // ================================================================================
ReportRequest(const IncidentReportArgs & a,const sp<IIncidentReportStatusListener> & listener,int fd)143 ReportRequest::ReportRequest(const IncidentReportArgs& a,
144                              const sp<IIncidentReportStatusListener>& listener, int fd)
145         :args(a),
146          mListener(listener),
147          mFd(fd),
148          mIsStreaming(fd >= 0),
149          mStatus(OK),
150          mZipPid(-1) {
151 }
152 
~ReportRequest()153 ReportRequest::~ReportRequest() {
154     if (mIsStreaming && mFd >= 0) {
155         // clean up the opened file descriptor
156         close(mFd);
157     }
158 }
159 
ok()160 bool ReportRequest::ok() {
161     if (mStatus != OK) {
162         return false;
163     }
164     if (!args.gzip()) {
165         return mFd >= 0;
166     }
167     // Send a blank signal to check if mZipPid is alive
168     return mZipPid > 0 && kill(mZipPid, 0) == 0;
169 }
170 
containsSection(int sectionId) const171 bool ReportRequest::containsSection(int sectionId) const {
172     return args.containsSection(sectionId, section_requires_specific_mention(sectionId));
173 }
174 
closeFd()175 void ReportRequest::closeFd() {
176     if (!mIsStreaming) {
177         return;
178     }
179     if (mFd >= 0) {
180         close(mFd);
181         mFd = -1;
182     }
183     if (mZipPid > 0) {
184         mZipPipe.close();
185         // Gzip may take some time.
186         status_t err = wait_child(mZipPid, /* timeout_ms= */ 10 * 1000);
187         if (err != 0) {
188             ALOGW("[ReportRequest] abnormal child process: %s", strerror(-err));
189         }
190     }
191 }
192 
getFd()193 int ReportRequest::getFd() {
194     return mZipPid > 0 ? mZipPipe.writeFd().get() : mFd;
195 }
196 
initGzipIfNecessary()197 status_t ReportRequest::initGzipIfNecessary() {
198     if (!mIsStreaming || !args.gzip()) {
199         return OK;
200     }
201     if (!mZipPipe.init()) {
202         ALOGE("[ReportRequest] Failed to setup pipe for gzip");
203         mStatus = -errno;
204         return mStatus;
205     }
206     int status = 0;
207     pid_t pid = fork_execute_cmd((char* const*)GZIP, mZipPipe.readFd().release(), mFd, &status);
208     if (pid < 0 || status != 0) {
209         mStatus = status;
210         return mStatus;
211     }
212     mZipPid = pid;
213     mFd = -1;
214     return OK;
215 }
216 
217 // ================================================================================
ReportBatch()218 ReportBatch::ReportBatch() {}
219 
~ReportBatch()220 ReportBatch::~ReportBatch() {}
221 
addPersistedReport(const IncidentReportArgs & args)222 void ReportBatch::addPersistedReport(const IncidentReportArgs& args) {
223     ComponentName component(args.receiverPkg(), args.receiverCls());
224     map<ComponentName, sp<ReportRequest>>::iterator found = mPersistedRequests.find(component);
225     if (found == mPersistedRequests.end()) {
226         // not found
227         mPersistedRequests[component] = new ReportRequest(args, nullptr, -1);
228     } else {
229         // found
230         sp<ReportRequest> request = found->second;
231         request->args.merge(args);
232     }
233 }
234 
addStreamingReport(const IncidentReportArgs & args,const sp<IIncidentReportStatusListener> & listener,int streamFd)235 void ReportBatch::addStreamingReport(const IncidentReportArgs& args,
236         const sp<IIncidentReportStatusListener>& listener, int streamFd) {
237     mStreamingRequests.push_back(new ReportRequest(args, listener, streamFd));
238 }
239 
empty() const240 bool ReportBatch::empty() const {
241     return mPersistedRequests.size() == 0 && mStreamingRequests.size() == 0;
242 }
243 
getPersistedRequest(const ComponentName & component)244 sp<ReportRequest> ReportBatch::getPersistedRequest(const ComponentName& component) {
245     map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.find(component);
246     if (it != mPersistedRequests.find(component)) {
247         return it->second;
248     } else {
249         return nullptr;
250     }
251 }
252 
forEachPersistedRequest(const function<void (const sp<ReportRequest> &)> & func)253 void ReportBatch::forEachPersistedRequest(const function<void (const sp<ReportRequest>&)>& func) {
254     for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
255             it != mPersistedRequests.end(); it++) {
256         func(it->second);
257     }
258 }
259 
forEachStreamingRequest(const function<void (const sp<ReportRequest> &)> & func)260 void ReportBatch::forEachStreamingRequest(const function<void (const sp<ReportRequest>&)>& func) {
261     for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
262             request != mStreamingRequests.end(); request++) {
263         func(*request);
264     }
265 }
266 
forEachListener(const function<void (const sp<IIncidentReportStatusListener> &)> & func)267 void ReportBatch::forEachListener(
268         const function<void (const sp<IIncidentReportStatusListener>&)>& func) {
269     for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
270             it != mPersistedRequests.end(); it++) {
271         sp<IIncidentReportStatusListener> listener = it->second->getListener();
272         if (listener != nullptr) {
273             func(listener);
274         }
275     }
276     for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
277             request != mStreamingRequests.end(); request++) {
278         sp<IIncidentReportStatusListener> listener = (*request)->getListener();
279         if (listener != nullptr) {
280             func(listener);
281         }
282     }
283 }
284 
forEachListener(int sectionId,const function<void (const sp<IIncidentReportStatusListener> &)> & func)285 void ReportBatch::forEachListener(int sectionId,
286         const function<void (const sp<IIncidentReportStatusListener>&)>& func) {
287     for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
288             it != mPersistedRequests.end(); it++) {
289         if (it->second->containsSection(sectionId)) {
290             sp<IIncidentReportStatusListener> listener = it->second->getListener();
291             if (listener != nullptr) {
292                 func(listener);
293             }
294         }
295     }
296     for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
297             request != mStreamingRequests.end(); request++) {
298         if ((*request)->containsSection(sectionId)) {
299             sp<IIncidentReportStatusListener> listener = (*request)->getListener();
300             if (listener != nullptr) {
301                 func(listener);
302             }
303         }
304     }
305 }
306 
getCombinedPersistedArgs(IncidentReportArgs * result)307 void ReportBatch::getCombinedPersistedArgs(IncidentReportArgs* result) {
308     for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
309             it != mPersistedRequests.end(); it++) {
310         result->merge(it->second->args);
311     }
312 }
313 
containsSection(int sectionId)314 bool ReportBatch::containsSection(int sectionId) {
315     // We don't cache this, because in case of error, we remove requests
316     // from the batch, and this is easier than recomputing the set.
317     for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
318             it != mPersistedRequests.end(); it++) {
319         if (it->second->containsSection(sectionId)) {
320             return true;
321         }
322     }
323     for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
324             request != mStreamingRequests.end(); request++) {
325         if ((*request)->containsSection(sectionId)) {
326             return true;
327         }
328     }
329     return false;
330 }
331 
clearPersistedRequests()332 void ReportBatch::clearPersistedRequests() {
333     mPersistedRequests.clear();
334 }
335 
transferStreamingRequests(const sp<ReportBatch> & that)336 void ReportBatch::transferStreamingRequests(const sp<ReportBatch>& that) {
337     for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
338             request != mStreamingRequests.end(); request++) {
339         that->mStreamingRequests.push_back(*request);
340     }
341     mStreamingRequests.clear();
342 }
343 
transferPersistedRequests(const sp<ReportBatch> & that)344 void ReportBatch::transferPersistedRequests(const sp<ReportBatch>& that) {
345     for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
346             it != mPersistedRequests.end(); it++) {
347         that->mPersistedRequests[it->first] = it->second;
348     }
349     mPersistedRequests.clear();
350 }
351 
getFailedRequests(vector<sp<ReportRequest>> * requests)352 void ReportBatch::getFailedRequests(vector<sp<ReportRequest>>* requests) {
353     for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
354             it != mPersistedRequests.end(); it++) {
355         if (it->second->getStatus() != NO_ERROR) {
356             requests->push_back(it->second);
357         }
358     }
359     for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
360             request != mStreamingRequests.end(); request++) {
361         if ((*request)->getStatus() != NO_ERROR) {
362             requests->push_back(*request);
363         }
364     }
365 }
366 
removeRequest(const sp<ReportRequest> & request)367 void ReportBatch::removeRequest(const sp<ReportRequest>& request) {
368     for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
369             it != mPersistedRequests.end(); it++) {
370         if (it->second == request) {
371             mPersistedRequests.erase(it);
372             return;
373         }
374     }
375     for (vector<sp<ReportRequest>>::iterator it = mStreamingRequests.begin();
376             it != mStreamingRequests.end(); it++) {
377         if (*it == request) {
378             mStreamingRequests.erase(it);
379             return;
380         }
381     }
382 }
383 
384 // ================================================================================
ReportWriter(const sp<ReportBatch> & batch)385 ReportWriter::ReportWriter(const sp<ReportBatch>& batch)
386         :mBatch(batch),
387          mPersistedFile(),
388          mMaxPersistedPrivacyPolicy(PRIVACY_POLICY_UNSET) {
389 }
390 
~ReportWriter()391 ReportWriter::~ReportWriter() {
392 }
393 
setPersistedFile(sp<ReportFile> file)394 void ReportWriter::setPersistedFile(sp<ReportFile> file) {
395     mPersistedFile = file;
396 }
397 
setMaxPersistedPrivacyPolicy(uint8_t privacyPolicy)398 void ReportWriter::setMaxPersistedPrivacyPolicy(uint8_t privacyPolicy) {
399     mMaxPersistedPrivacyPolicy = privacyPolicy;
400 }
401 
startSection(int sectionId)402 void ReportWriter::startSection(int sectionId) {
403     mCurrentSectionId = sectionId;
404     mSectionStartTimeMs = uptimeMillis();
405 
406     mSectionStatsCalledForSectionId = -1;
407     mDumpSizeBytes = 0;
408     mDumpDurationMs = 0;
409     mSectionTimedOut = false;
410     mSectionTruncated = false;
411     mSectionBufferSuccess = false;
412     mHadError = false;
413     mSectionErrors.clear();
414 }
415 
setSectionStats(const FdBuffer & buffer)416 void ReportWriter::setSectionStats(const FdBuffer& buffer) {
417     mSectionStatsCalledForSectionId = mCurrentSectionId;
418     mDumpSizeBytes = buffer.size();
419     mDumpDurationMs = buffer.durationMs();
420     mSectionTimedOut = buffer.timedOut();
421     mSectionTruncated = buffer.truncated();
422     mSectionBufferSuccess = !buffer.timedOut() && !buffer.truncated();
423 }
424 
endSection(IncidentMetadata::SectionStats * sectionMetadata)425 void ReportWriter::endSection(IncidentMetadata::SectionStats* sectionMetadata) {
426     long endTime = uptimeMillis();
427 
428     if (mSectionStatsCalledForSectionId != mCurrentSectionId) {
429         ALOGW("setSectionStats not called for section %d", mCurrentSectionId);
430     }
431 
432     sectionMetadata->set_id(mCurrentSectionId);
433     sectionMetadata->set_success((!mHadError) && mSectionBufferSuccess);
434     sectionMetadata->set_report_size_bytes(mMaxSectionDataFilteredSize);
435     sectionMetadata->set_exec_duration_ms(endTime - mSectionStartTimeMs);
436     sectionMetadata->set_dump_size_bytes(mDumpSizeBytes);
437     sectionMetadata->set_dump_duration_ms(mDumpDurationMs);
438     sectionMetadata->set_timed_out(mSectionTimedOut);
439     sectionMetadata->set_is_truncated(mSectionTruncated);
440     sectionMetadata->set_error_msg(mSectionErrors);
441 }
442 
warning(const Section * section,status_t err,const char * format,...)443 void ReportWriter::warning(const Section* section, status_t err, const char* format, ...) {
444     va_list args;
445     va_start(args, format);
446     vflog(section, err, ANDROID_LOG_ERROR, "error", format, args);
447     va_end(args);
448 }
449 
error(const Section * section,status_t err,const char * format,...)450 void ReportWriter::error(const Section* section, status_t err, const char* format, ...) {
451     va_list args;
452     va_start(args, format);
453     vflog(section, err, ANDROID_LOG_WARN, "warning", format, args);
454     va_end(args);
455 }
456 
vflog(const Section * section,status_t err,int level,const char * levelText,const char * format,va_list args)457 void ReportWriter::vflog(const Section* section, status_t err, int level, const char* levelText,
458         const char* format, va_list args) {
459     const char* prefixFormat = "%s in section %d (%d) '%s': ";
460     int prefixLen = snprintf(NULL, 0, prefixFormat, levelText, section->id,
461             err, strerror(-err));
462 
463     va_list measureArgs;
464     va_copy(measureArgs, args);
465     int messageLen = vsnprintf(NULL, 0, format, args);
466     va_end(measureArgs);
467 
468     char* line = (char*)malloc(prefixLen + messageLen + 1);
469     if (line == NULL) {
470         // All hope is lost, just give up.
471         return;
472     }
473 
474     sprintf(line, prefixFormat, levelText, section->id, err, strerror(-err));
475 
476     vsprintf(line + prefixLen, format, args);
477 
478     __android_log_write(level, LOG_TAG, line);
479 
480     if (mSectionErrors.length() == 0) {
481         mSectionErrors = line;
482     } else {
483         mSectionErrors += '\n';
484         mSectionErrors += line;
485     }
486 
487     free(line);
488 
489     if (level >= ANDROID_LOG_ERROR) {
490         mHadError = true;
491     }
492 }
493 
494 // Reads data from FdBuffer and writes it to the requests file descriptor.
writeSection(const FdBuffer & buffer)495 status_t ReportWriter::writeSection(const FdBuffer& buffer) {
496     PrivacyFilter filter(mCurrentSectionId, get_privacy_of_section(mCurrentSectionId));
497 
498     // Add the fd for the persisted requests
499     if (mPersistedFile != nullptr) {
500         filter.addFd(new PersistedFilterFd(mMaxPersistedPrivacyPolicy,
501                     mPersistedFile->getDataFileFd(), mPersistedFile));
502     }
503 
504     // Add the fds for the streamed requests
505     mBatch->forEachStreamingRequest([&filter, this](const sp<ReportRequest>& request) {
506         if (request->ok()
507                 && request->args.containsSection(mCurrentSectionId,
508                     section_requires_specific_mention(mCurrentSectionId))) {
509             filter.addFd(new StreamingFilterFd(request->args.getPrivacyPolicy(),
510                         request->getFd(), request));
511         }
512     });
513 
514     return filter.writeData(buffer, PRIVACY_POLICY_LOCAL, &mMaxSectionDataFilteredSize);
515 }
516 
517 
518 // ================================================================================
Reporter(const sp<WorkDirectory> & workDirectory,const sp<ReportBatch> & batch,const vector<BringYourOwnSection * > & registeredSections)519 Reporter::Reporter(const sp<WorkDirectory>& workDirectory,
520                    const sp<ReportBatch>& batch,
521                    const vector<BringYourOwnSection*>& registeredSections)
522         :mWorkDirectory(workDirectory),
523          mWriter(batch),
524          mBatch(batch),
525          mRegisteredSections(registeredSections) {
526 }
527 
~Reporter()528 Reporter::~Reporter() {
529 }
530 
runReport(size_t * reportByteSize)531 void Reporter::runReport(size_t* reportByteSize) {
532     status_t err = NO_ERROR;
533 
534     IncidentMetadata metadata;
535     int persistedPrivacyPolicy = PRIVACY_POLICY_UNSET;
536 
537     (*reportByteSize) = 0;
538 
539     // Tell everyone that we're starting.
540     ALOGI("Starting incident report");
541     mBatch->forEachListener([](const auto& listener) { listener->onReportStarted(); });
542 
543     if (mBatch->hasPersistedReports()) {
544         // Open a work file to contain the contents of all of the persisted reports.
545         // For this block, if we can't initialize the report file for some reason,
546         // then we will remove the persisted ReportRequests from the report, but
547         // continue with the streaming ones.
548         mPersistedFile = mWorkDirectory->createReportFile();
549         ALOGI("Report will be persisted: envelope: %s  data: %s",
550                 mPersistedFile->getEnvelopeFileName().c_str(),
551                 mPersistedFile->getDataFileName().c_str());
552 
553         // Record all of the metadata to the persisted file's metadata file.
554         // It will be read from there and reconstructed as the actual reports
555         // are sent out.
556         if (mPersistedFile != nullptr) {
557             mBatch->forEachPersistedRequest([this, &persistedPrivacyPolicy](
558                         const sp<ReportRequest>& request) {
559                 mPersistedFile->addReport(request->args);
560                 if (request->args.getPrivacyPolicy() < persistedPrivacyPolicy) {
561                     persistedPrivacyPolicy = request->args.getPrivacyPolicy();
562                 }
563             });
564             mPersistedFile->setMaxPersistedPrivacyPolicy(persistedPrivacyPolicy);
565             err = mPersistedFile->saveEnvelope();
566             if (err != NO_ERROR) {
567                 mWorkDirectory->remove(mPersistedFile);
568                 mPersistedFile = nullptr;
569             }
570             mWriter.setMaxPersistedPrivacyPolicy(persistedPrivacyPolicy);
571         }
572 
573         if (mPersistedFile != nullptr) {
574             err = mPersistedFile->startWritingDataFile();
575             if (err != NO_ERROR) {
576                 mWorkDirectory->remove(mPersistedFile);
577                 mPersistedFile = nullptr;
578             }
579         }
580 
581         if (mPersistedFile != nullptr) {
582             mWriter.setPersistedFile(mPersistedFile);
583         } else {
584             ALOGW("Error creating the persisted file, so clearing persisted reports.");
585             // If we couldn't open the file (permissions err, etc), then
586             // we still want to proceed with any streaming reports, but
587             // cancel all of the persisted ones.
588             mBatch->forEachPersistedRequest([](const sp<ReportRequest>& request) {
589                 sp<IIncidentReportStatusListener> listener = request->getListener();
590                 if (listener != nullptr) {
591                     listener->onReportFailed();
592                 }
593             });
594             mBatch->clearPersistedRequests();
595         }
596     }
597 
598     // If we have a persisted ID, then we allow all the readers to see that.  There's
599     // enough in the data to allow for a join, and nothing in here that intrisincally
600     // could ever prevent that, so just give them the ID.  If we don't have that then we
601     // make and ID that's extremely likely to be unique, but clock resetting could allow
602     // it to be duplicate.
603     int64_t reportId;
604     if (mPersistedFile != nullptr) {
605         reportId = mPersistedFile->getTimestampNs();
606     } else {
607         struct timespec spec;
608         clock_gettime(CLOCK_REALTIME, &spec);
609         reportId = (spec.tv_sec) * 1000 + spec.tv_nsec;
610     }
611 
612     mBatch->forEachStreamingRequest([](const sp<ReportRequest>& request) {
613         status_t err = request->initGzipIfNecessary();
614         if (err != 0) {
615             ALOGW("Error forking gzip: %s", strerror(err));
616         }
617     });
618 
619     // Write the incident report headers - each request gets its own headers.  It's different
620     // from the other top-level fields in IncidentReport that are the sections where the rest
621     // is all shared data (although with their own individual privacy filtering).
622     mBatch->forEachStreamingRequest([](const sp<ReportRequest>& request) {
623         const vector<vector<uint8_t>>& headers = request->args.headers();
624         for (vector<vector<uint8_t>>::const_iterator buf = headers.begin(); buf != headers.end();
625              buf++) {
626             // If there was an error now, there will be an error later and we will remove
627             // it from the list then.
628             write_header_section(request->getFd(), buf->data(), buf->size());
629         }
630     });
631 
632     // If writing to any of the headers failed, we don't want to keep processing
633     // sections for it.
634     cancel_and_remove_failed_requests();
635 
636     // For each of the report fields, see if we need it, and if so, execute the command
637     // and report to those that care that we're doing it.
638     for (const Section** section = SECTION_LIST; *section; section++) {
639         if (execute_section(*section, &metadata, reportByteSize) != NO_ERROR) {
640             goto DONE;
641         }
642     }
643 
644     for (const Section* section : mRegisteredSections) {
645         if (execute_section(section, &metadata, reportByteSize) != NO_ERROR) {
646             goto DONE;
647         }
648     }
649 
650 DONE:
651     // Finish up the persisted file.
652     if (mPersistedFile != nullptr) {
653         mPersistedFile->closeDataFile();
654 
655         // Set the stored metadata
656         IncidentReportArgs combinedArgs;
657         mBatch->getCombinedPersistedArgs(&combinedArgs);
658         IncidentMetadata persistedMetadata;
659         make_metadata(&persistedMetadata, metadata, mPersistedFile->getTimestampNs(),
660                 persistedPrivacyPolicy, combinedArgs);
661         mPersistedFile->setMetadata(persistedMetadata);
662 
663         mPersistedFile->markCompleted();
664         err = mPersistedFile->saveEnvelope();
665         if (err != NO_ERROR) {
666             ALOGW("mPersistedFile->saveEnvelope returned %s. Won't send broadcast",
667                     strerror(-err));
668             // Abandon ship.
669             mWorkDirectory->remove(mPersistedFile);
670         }
671     }
672 
673     // Write the metadata to the streaming ones
674     mBatch->forEachStreamingRequest([reportId, &metadata](const sp<ReportRequest>& request) {
675         IncidentMetadata streamingMetadata;
676         make_metadata(&streamingMetadata, metadata, reportId,
677                 request->args.getPrivacyPolicy(), request);
678         status_t nonFatalErr = write_section(request->getFd(), FIELD_ID_METADATA,
679                 streamingMetadata);
680         if (nonFatalErr != NO_ERROR) {
681             ALOGW("Error writing the metadata to streaming incident report.  This is the last"
682                     " thing so we won't return an error: %s", strerror(nonFatalErr));
683         }
684     });
685 
686     // Finish up the streaming ones.
687     mBatch->forEachStreamingRequest([](const sp<ReportRequest>& request) {
688         request->closeFd();
689     });
690 
691     // Tell the listeners that we're done.
692     if (err == NO_ERROR) {
693         mBatch->forEachListener([](const auto& listener) {
694             listener->onReportFinished();
695         });
696     } else {
697         mBatch->forEachListener([](const auto& listener) {
698             listener->onReportFailed();
699         });
700     }
701     clear_buffer_pool();
702     ALOGI("Done taking incident report err=%s", strerror(-err));
703 }
704 
execute_section(const Section * section,IncidentMetadata * metadata,size_t * reportByteSize)705 status_t Reporter::execute_section(const Section* section, IncidentMetadata* metadata,
706         size_t* reportByteSize) {
707     const int sectionId = section->id;
708 
709     // If nobody wants this section, skip it.
710     if (!mBatch->containsSection(sectionId)) {
711         return NO_ERROR;
712     }
713 
714     ALOGD("Start incident report section %d '%s'", sectionId, section->name.string());
715     IncidentMetadata::SectionStats* sectionMetadata = metadata->add_sections();
716 
717     // Notify listener of starting
718     mBatch->forEachListener(sectionId, [sectionId](const auto& listener) {
719         listener->onReportSectionStatus(
720                 sectionId, IIncidentReportStatusListener::STATUS_STARTING);
721     });
722 
723     // Go get the data and write it into the file descriptors.
724     mWriter.startSection(sectionId);
725     status_t err = section->Execute(&mWriter);
726     mWriter.endSection(sectionMetadata);
727 
728     // Sections returning errors are fatal. Most errors should not be fatal.
729     if (err != NO_ERROR) {
730         mWriter.error(section, err, "Section failed. Stopping report.");
731         return err;
732     }
733 
734     // The returned max data size is used for throttling too many incident reports.
735     (*reportByteSize) += sectionMetadata->report_size_bytes();
736 
737     // For any requests that failed during this section, remove them now.  We do this
738     // before calling back about section finished, so listeners do not erroniously get the
739     // impression that the section succeeded.  But we do it here instead of inside
740     // writeSection so that the callback is done from a known context and not from the
741     // bowels of a section, where changing the batch could cause odd errors.
742     cancel_and_remove_failed_requests();
743 
744     // Notify listener of finishing
745     mBatch->forEachListener(sectionId, [sectionId](const auto& listener) {
746             listener->onReportSectionStatus(
747                     sectionId, IIncidentReportStatusListener::STATUS_FINISHED);
748     });
749 
750     ALOGD("Finish incident report section %d '%s'", sectionId, section->name.string());
751     return NO_ERROR;
752 }
753 
cancel_and_remove_failed_requests()754 void Reporter::cancel_and_remove_failed_requests() {
755     // Handle a failure in the persisted file
756     if (mPersistedFile != nullptr) {
757         if (mPersistedFile->getWriteError() != NO_ERROR) {
758             ALOGW("Error writing to the persisted file (%s). Closing it and canceling.",
759                     strerror(-mPersistedFile->getWriteError()));
760             mBatch->forEachPersistedRequest([this](const sp<ReportRequest>& request) {
761                 sp<IIncidentReportStatusListener> listener = request->getListener();
762                 if (listener != nullptr) {
763                     listener->onReportFailed();
764                 }
765                 mBatch->removeRequest(request);
766             });
767             mWriter.setPersistedFile(nullptr);
768             mPersistedFile->closeDataFile();
769             mWorkDirectory->remove(mPersistedFile);
770             mPersistedFile = nullptr;
771         }
772     }
773 
774     // Handle failures in the streaming files
775     vector<sp<ReportRequest>> failed;
776     mBatch->getFailedRequests(&failed);
777     for (sp<ReportRequest>& request: failed) {
778         ALOGW("Error writing to a request stream (%s). Closing it and canceling.",
779                 strerror(-request->getStatus()));
780         sp<IIncidentReportStatusListener> listener = request->getListener();
781         if (listener != nullptr) {
782             listener->onReportFailed();
783         }
784         request->closeFd();  // Will only close the streaming ones.
785         mBatch->removeRequest(request);
786     }
787 }
788 
789 }  // namespace incidentd
790 }  // namespace os
791 }  // namespace android
792