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