blob: dc4065bce39bd212ff04bd724fb7880019324447 [file] [log] [blame]
Joe Onorato1754d742016-11-21 17:51:35 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Yi Jin4e843102018-02-14 15:36:18 -080016#define DEBUG false
Yi Jinb592e3b2018-02-01 15:17:04 -080017#include "Log.h"
Joe Onorato1754d742016-11-21 17:51:35 -080018
19#include "Reporter.h"
Joe Onorato1754d742016-11-21 17:51:35 -080020
Joe Onorato99598ee2019-02-11 15:55:13 +000021#include "incidentd_util.h"
Yi Jin329130b2018-02-09 16:47:47 -080022#include "Privacy.h"
Joe Onorato99598ee2019-02-11 15:55:13 +000023#include "PrivacyFilter.h"
24#include "proto_util.h"
Joe Onorato1754d742016-11-21 17:51:35 -080025#include "report_directory.h"
26#include "section_list.h"
27
Joe Onorato99598ee2019-02-11 15:55:13 +000028#include <android-base/file.h>
Joe Onorato1754d742016-11-21 17:51:35 -080029#include <android/os/DropBoxManager.h>
Joe Onorato99598ee2019-02-11 15:55:13 +000030#include <android/util/protobuf.h>
31#include <android/util/ProtoOutputStream.h>
Yi Jin0a3406f2017-06-22 19:23:11 -070032#include <private/android_filesystem_config.h>
Joe Onorato1754d742016-11-21 17:51:35 -080033#include <utils/SystemClock.h>
34
Joe Onorato1754d742016-11-21 17:51:35 -080035#include <dirent.h>
Joe Onorato1754d742016-11-21 17:51:35 -080036#include <errno.h>
Yi Jinb592e3b2018-02-01 15:17:04 -080037#include <fcntl.h>
38#include <sys/stat.h>
39#include <sys/types.h>
Kweku Adams3d160912018-05-07 11:26:27 -070040#include <string>
Joe Onorato99598ee2019-02-11 15:55:13 +000041#include <time.h>
Joe Onorato1754d742016-11-21 17:51:35 -080042
Yi Jin6cacbcb2018-03-30 14:04:52 -070043namespace android {
44namespace os {
45namespace incidentd {
46
Joe Onorato99598ee2019-02-11 15:55:13 +000047using namespace android::util;
48
49/**
50 * The field id of the metadata section from
51 * frameworks/base/core/proto/android/os/incident.proto
52 */
53const int FIELD_ID_METADATA = 2;
54
55IncidentMetadata_Destination privacy_policy_to_dest(uint8_t privacyPolicy) {
56 switch (privacyPolicy) {
57 case PRIVACY_POLICY_AUTOMATIC:
58 return IncidentMetadata_Destination_AUTOMATIC;
59 case PRIVACY_POLICY_EXPLICIT:
60 return IncidentMetadata_Destination_EXPLICIT;
61 case PRIVACY_POLICY_LOCAL:
62 return IncidentMetadata_Destination_LOCAL;
63 default:
64 // Anything else reverts to automatic
65 return IncidentMetadata_Destination_AUTOMATIC;
66 }
67}
68
Joe Onorato99598ee2019-02-11 15:55:13 +000069
Joe Onorato7a406b42019-04-12 18:11:30 -070070static bool contains_section(const IncidentReportArgs& args, int sectionId) {
71 return args.containsSection(sectionId, section_requires_specific_mention(sectionId));
72}
73
74static bool contains_section(const sp<ReportRequest>& args, int sectionId) {
75 return args->containsSection(sectionId);
Joe Onorato99598ee2019-02-11 15:55:13 +000076}
77
78// ARGS must have a containsSection(int) method
Joe Onorato7a406b42019-04-12 18:11:30 -070079template <typename ARGS>
80void make_metadata(IncidentMetadata* result, const IncidentMetadata& full,
Joe Onorato99598ee2019-02-11 15:55:13 +000081 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);
Joe Onorato7a406b42019-04-12 18:11:30 -070088 if (contains_section(args, sectionStats.id())) {
Joe Onorato99598ee2019-02-11 15:55:13 +000089 *result->add_sections() = sectionStats;
90 }
91 }
92}
93
94// ================================================================================
95class StreamingFilterFd : public FilterFd {
96public:
97 StreamingFilterFd(uint8_t privacyPolicy, int fd, const sp<ReportRequest>& request);
98
99 virtual void onWriteError(status_t err);
100
101private:
102 sp<ReportRequest> mRequest;
103};
104
105StreamingFilterFd::StreamingFilterFd(uint8_t privacyPolicy, int fd,
106 const sp<ReportRequest>& request)
107 :FilterFd(privacyPolicy, fd),
108 mRequest(request) {
109}
110
111void StreamingFilterFd::onWriteError(status_t err) {
112 mRequest->setStatus(err);
113}
114
115
116// ================================================================================
117class PersistedFilterFd : public FilterFd {
118public:
119 PersistedFilterFd(uint8_t privacyPolicy, int fd, const sp<ReportFile>& reportFile);
120
121 virtual void onWriteError(status_t err);
122
123private:
124 sp<ReportFile> mReportFile;
125};
126
127PersistedFilterFd::PersistedFilterFd(uint8_t privacyPolicy, int fd,
128 const sp<ReportFile>& reportFile)
129 :FilterFd(privacyPolicy, fd),
130 mReportFile(reportFile) {
131}
132
133void PersistedFilterFd::onWriteError(status_t err) {
134 mReportFile->setWriteError(err);
135}
136
137
Yi Jin0a3406f2017-06-22 19:23:11 -0700138// ================================================================================
Joe Onorato1754d742016-11-21 17:51:35 -0800139ReportRequest::ReportRequest(const IncidentReportArgs& a,
Joe Onorato99598ee2019-02-11 15:55:13 +0000140 const sp<IIncidentReportStatusListener>& listener, int fd)
141 :args(a),
142 mListener(listener),
143 mFd(fd),
144 mIsStreaming(fd >= 0),
145 mStatus(NO_ERROR) {
146}
Joe Onorato1754d742016-11-21 17:51:35 -0800147
Yi Jinb592e3b2018-02-01 15:17:04 -0800148ReportRequest::~ReportRequest() {
Joe Onorato99598ee2019-02-11 15:55:13 +0000149 if (mIsStreaming && mFd >= 0) {
Yi Jin22769e02017-10-16 14:42:50 -0700150 // clean up the opened file descriptor
Joe Onorato99598ee2019-02-11 15:55:13 +0000151 close(mFd);
Yi Jin22769e02017-10-16 14:42:50 -0700152 }
Joe Onorato1754d742016-11-21 17:51:35 -0800153}
154
Joe Onorato99598ee2019-02-11 15:55:13 +0000155bool ReportRequest::ok() {
156 return mFd >= 0 && mStatus == NO_ERROR;
Joe Onorato1754d742016-11-21 17:51:35 -0800157}
158
Joe Onorato7a406b42019-04-12 18:11:30 -0700159bool ReportRequest::containsSection(int sectionId) const {
160 return args.containsSection(sectionId, section_requires_specific_mention(sectionId));
161}
162
Joe Onorato99598ee2019-02-11 15:55:13 +0000163void ReportRequest::closeFd() {
164 if (mIsStreaming && mFd >= 0) {
165 close(mFd);
166 mFd = -1;
Yi Jin329130b2018-02-09 16:47:47 -0800167 }
Yi Jin3ec5cc72018-01-26 13:42:43 -0800168}
169
Joe Onorato1754d742016-11-21 17:51:35 -0800170// ================================================================================
Joe Onorato99598ee2019-02-11 15:55:13 +0000171ReportBatch::ReportBatch() {}
Yi Jinadd11e92017-07-30 16:10:07 -0700172
Joe Onorato99598ee2019-02-11 15:55:13 +0000173ReportBatch::~ReportBatch() {}
Joe Onorato1754d742016-11-21 17:51:35 -0800174
Joe Onorato99598ee2019-02-11 15:55:13 +0000175void ReportBatch::addPersistedReport(const IncidentReportArgs& args) {
176 ComponentName component(args.receiverPkg(), args.receiverCls());
177 map<ComponentName, sp<ReportRequest>>::iterator found = mPersistedRequests.find(component);
178 if (found == mPersistedRequests.end()) {
179 // not found
180 mPersistedRequests[component] = new ReportRequest(args, nullptr, -1);
181 } else {
182 // found
183 sp<ReportRequest> request = found->second;
184 request->args.merge(args);
185 }
Joe Onorato1754d742016-11-21 17:51:35 -0800186}
187
Joe Onorato99598ee2019-02-11 15:55:13 +0000188void ReportBatch::addStreamingReport(const IncidentReportArgs& args,
189 const sp<IIncidentReportStatusListener>& listener, int streamFd) {
190 mStreamingRequests.push_back(new ReportRequest(args, listener, streamFd));
191}
Joe Onorato1754d742016-11-21 17:51:35 -0800192
Joe Onorato99598ee2019-02-11 15:55:13 +0000193bool ReportBatch::empty() const {
194 return mPersistedRequests.size() == 0 && mStreamingRequests.size() == 0;
195}
196
197sp<ReportRequest> ReportBatch::getPersistedRequest(const ComponentName& component) {
198 map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.find(component);
199 if (it != mPersistedRequests.find(component)) {
200 return it->second;
201 } else {
202 return nullptr;
203 }
204}
205
206void ReportBatch::forEachPersistedRequest(const function<void (const sp<ReportRequest>&)>& func) {
207 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
208 it != mPersistedRequests.end(); it++) {
209 func(it->second);
210 }
211}
212
213void ReportBatch::forEachStreamingRequest(const function<void (const sp<ReportRequest>&)>& func) {
214 for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
215 request != mStreamingRequests.end(); request++) {
216 func(*request);
217 }
218}
219
220void ReportBatch::forEachListener(
221 const function<void (const sp<IIncidentReportStatusListener>&)>& func) {
222 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
223 it != mPersistedRequests.end(); it++) {
224 sp<IIncidentReportStatusListener> listener = it->second->getListener();
225 if (listener != nullptr) {
226 func(listener);
227 }
228 }
229 for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
230 request != mStreamingRequests.end(); request++) {
231 sp<IIncidentReportStatusListener> listener = (*request)->getListener();
232 if (listener != nullptr) {
233 func(listener);
234 }
235 }
236}
237
238void ReportBatch::forEachListener(int sectionId,
239 const function<void (const sp<IIncidentReportStatusListener>&)>& func) {
240 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
241 it != mPersistedRequests.end(); it++) {
242 if (it->second->containsSection(sectionId)) {
243 sp<IIncidentReportStatusListener> listener = it->second->getListener();
244 if (listener != nullptr) {
245 func(listener);
246 }
247 }
248 }
249 for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
250 request != mStreamingRequests.end(); request++) {
251 if ((*request)->containsSection(sectionId)) {
252 sp<IIncidentReportStatusListener> listener = (*request)->getListener();
253 if (listener != nullptr) {
254 func(listener);
255 }
256 }
257 }
258}
259
260void ReportBatch::getCombinedPersistedArgs(IncidentReportArgs* result) {
261 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
262 it != mPersistedRequests.end(); it++) {
263 result->merge(it->second->args);
264 }
265}
266
267bool ReportBatch::containsSection(int sectionId) {
268 // We don't cache this, because in case of error, we remove requests
269 // from the batch, and this is easier than recomputing the set.
270 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
271 it != mPersistedRequests.end(); it++) {
272 if (it->second->containsSection(sectionId)) {
273 return true;
274 }
275 }
276 for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
277 request != mStreamingRequests.end(); request++) {
278 if ((*request)->containsSection(sectionId)) {
279 return true;
280 }
281 }
282 return false;
283}
284
285void ReportBatch::clearPersistedRequests() {
286 mPersistedRequests.clear();
287}
288
Joe Onoratoe5472052019-04-24 16:27:33 -0700289void 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
297void 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
Joe Onorato99598ee2019-02-11 15:55:13 +0000305void 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
320void 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// ================================================================================
338ReportWriter::ReportWriter(const sp<ReportBatch>& batch)
339 :mBatch(batch),
340 mPersistedFile(),
341 mMaxPersistedPrivacyPolicy(PRIVACY_POLICY_UNSET) {
342}
343
344ReportWriter::~ReportWriter() {
345}
346
347void ReportWriter::setPersistedFile(sp<ReportFile> file) {
348 mPersistedFile = file;
349}
350
351void ReportWriter::setMaxPersistedPrivacyPolicy(uint8_t privacyPolicy) {
352 mMaxPersistedPrivacyPolicy = privacyPolicy;
353}
354
355void 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
370void 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
379void 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
397void 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
404void 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
411void 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.
449status_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) {
Joe Onorato7a406b42019-04-12 18:11:30 -0700460 if (request->ok()
461 && request->args.containsSection(mCurrentSectionId,
462 section_requires_specific_mention(mCurrentSectionId))) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000463 filter.addFd(new StreamingFilterFd(request->args.getPrivacyPolicy(),
464 request->getFd(), request));
465 }
466 });
467
Yao Chen43706b42019-04-21 14:34:30 -0700468 return filter.writeData(buffer, PRIVACY_POLICY_LOCAL, &mMaxSectionDataFilteredSize,
469 true /*encrypt if needed*/);
Joe Onorato99598ee2019-02-11 15:55:13 +0000470}
471
472
473// ================================================================================
474Reporter::Reporter(const sp<WorkDirectory>& workDirectory, const sp<ReportBatch>& batch)
475 :mWorkDirectory(workDirectory),
476 mWriter(batch),
477 mBatch(batch) {
478}
479
480Reporter::~Reporter() {
481}
482
483void Reporter::runReport(size_t* reportByteSize) {
Joe Onorato1754d742016-11-21 17:51:35 -0800484 status_t err = NO_ERROR;
Joe Onorato99598ee2019-02-11 15:55:13 +0000485
486 IncidentMetadata metadata;
487 int persistedPrivacyPolicy = PRIVACY_POLICY_UNSET;
Joe Onorato1754d742016-11-21 17:51:35 -0800488
Joe Onorato99598ee2019-02-11 15:55:13 +0000489 (*reportByteSize) = 0;
Joe Onorato1754d742016-11-21 17:51:35 -0800490
491 // Tell everyone that we're starting.
Joe Onorato99598ee2019-02-11 15:55:13 +0000492 ALOGI("Starting incident report");
493 mBatch->forEachListener([](const auto& listener) { listener->onReportStarted(); });
494
495 if (mBatch->hasPersistedReports()) {
496 // Open a work file to contain the contents of all of the persisted reports.
497 // For this block, if we can't initialize the report file for some reason,
498 // then we will remove the persisted ReportRequests from the report, but
499 // continue with the streaming ones.
500 mPersistedFile = mWorkDirectory->createReportFile();
501 ALOGI("Report will be persisted: envelope: %s data: %s",
502 mPersistedFile->getEnvelopeFileName().c_str(),
503 mPersistedFile->getDataFileName().c_str());
504
505 // Record all of the metadata to the persisted file's metadata file.
506 // It will be read from there and reconstructed as the actual reports
507 // are sent out.
508 if (mPersistedFile != nullptr) {
509 mBatch->forEachPersistedRequest([this, &persistedPrivacyPolicy](
510 const sp<ReportRequest>& request) {
511 mPersistedFile->addReport(request->args);
512 if (request->args.getPrivacyPolicy() < persistedPrivacyPolicy) {
513 persistedPrivacyPolicy = request->args.getPrivacyPolicy();
514 }
515 });
516 mPersistedFile->setMaxPersistedPrivacyPolicy(persistedPrivacyPolicy);
517 err = mPersistedFile->saveEnvelope();
518 if (err != NO_ERROR) {
519 mWorkDirectory->remove(mPersistedFile);
520 mPersistedFile = nullptr;
521 }
522 mWriter.setMaxPersistedPrivacyPolicy(persistedPrivacyPolicy);
523 }
524
525 if (mPersistedFile != nullptr) {
526 err = mPersistedFile->startWritingDataFile();
527 if (err != NO_ERROR) {
528 mWorkDirectory->remove(mPersistedFile);
529 mPersistedFile = nullptr;
530 }
531 }
532
533 if (mPersistedFile != nullptr) {
534 mWriter.setPersistedFile(mPersistedFile);
535 } else {
536 ALOGW("Error creating the persisted file, so clearing persisted reports.");
537 // If we couldn't open the file (permissions err, etc), then
538 // we still want to proceed with any streaming reports, but
539 // cancel all of the persisted ones.
540 mBatch->forEachPersistedRequest([](const sp<ReportRequest>& request) {
541 sp<IIncidentReportStatusListener> listener = request->getListener();
542 if (listener != nullptr) {
543 listener->onReportFailed();
544 }
545 });
546 mBatch->clearPersistedRequests();
Joe Onorato1754d742016-11-21 17:51:35 -0800547 }
548 }
549
Joe Onorato99598ee2019-02-11 15:55:13 +0000550 // If we have a persisted ID, then we allow all the readers to see that. There's
551 // enough in the data to allow for a join, and nothing in here that intrisincally
552 // could ever prevent that, so just give them the ID. If we don't have that then we
553 // make and ID that's extremely likely to be unique, but clock resetting could allow
554 // it to be duplicate.
555 int64_t reportId;
556 if (mPersistedFile != nullptr) {
557 reportId = mPersistedFile->getTimestampNs();
558 } else {
559 struct timespec spec;
560 clock_gettime(CLOCK_REALTIME, &spec);
561 reportId = (spec.tv_sec) * 1000 + spec.tv_nsec;
562 }
563
564 // Write the incident report headers - each request gets its own headers. It's different
565 // from the other top-level fields in IncidentReport that are the sections where the rest
566 // is all shared data (although with their own individual privacy filtering).
567 mBatch->forEachStreamingRequest([](const sp<ReportRequest>& request) {
568 const vector<vector<uint8_t>>& headers = request->args.headers();
569 for (vector<vector<uint8_t>>::const_iterator buf = headers.begin(); buf != headers.end();
570 buf++) {
571 // If there was an error now, there will be an error later and we will remove
572 // it from the list then.
Yao Chencbafce92019-04-01 15:56:44 -0700573 write_header_section(request->getFd(), buf->data(), buf->size());
Joe Onorato99598ee2019-02-11 15:55:13 +0000574 }
575 });
576
577 // If writing to any of the headers failed, we don't want to keep processing
578 // sections for it.
579 cancel_and_remove_failed_requests();
Joe Onorato1754d742016-11-21 17:51:35 -0800580
581 // For each of the report fields, see if we need it, and if so, execute the command
582 // and report to those that care that we're doing it.
Yi Jinb592e3b2018-02-01 15:17:04 -0800583 for (const Section** section = SECTION_LIST; *section; section++) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000584 const int sectionId = (*section)->id;
585
Joe Onorato99598ee2019-02-11 15:55:13 +0000586 // If nobody wants this section, skip it.
587 if (!mBatch->containsSection(sectionId)) {
588 continue;
Joe Onorato1754d742016-11-21 17:51:35 -0800589 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000590
591 ALOGD("Start incident report section %d '%s'", sectionId, (*section)->name.string());
592 IncidentMetadata::SectionStats* sectionMetadata = metadata.add_sections();
593
594 // Notify listener of starting
595 mBatch->forEachListener(sectionId, [sectionId](const auto& listener) {
596 listener->onReportSectionStatus(
597 sectionId, IIncidentReportStatusListener::STATUS_STARTING);
598 });
599
600 // Go get the data and write it into the file descriptors.
601 mWriter.startSection(sectionId);
602 err = (*section)->Execute(&mWriter);
603 mWriter.endSection(sectionMetadata);
604
605 // Sections returning errors are fatal. Most errors should not be fatal.
606 if (err != NO_ERROR) {
607 mWriter.error((*section), err, "Section failed. Stopping report.");
608 goto DONE;
609 }
610
611 // The returned max data size is used for throttling too many incident reports.
612 (*reportByteSize) += sectionMetadata->report_size_bytes();
613
614 // For any requests that failed during this section, remove them now. We do this
615 // before calling back about section finished, so listeners do not erroniously get the
616 // impression that the section succeeded. But we do it here instead of inside
617 // writeSection so that the callback is done from a known context and not from the
618 // bowels of a section, where changing the batch could cause odd errors.
619 cancel_and_remove_failed_requests();
620
621 // Notify listener of finishing
622 mBatch->forEachListener(sectionId, [sectionId](const auto& listener) {
623 listener->onReportSectionStatus(
624 sectionId, IIncidentReportStatusListener::STATUS_FINISHED);
625 });
626
627 ALOGD("Finish incident report section %d '%s'", sectionId, (*section)->name.string());
Joe Onorato1754d742016-11-21 17:51:35 -0800628 }
629
Yi Jinedfd5bb2017-09-06 17:09:11 -0700630DONE:
Joe Onorato99598ee2019-02-11 15:55:13 +0000631 // Finish up the persisted file.
632 if (mPersistedFile != nullptr) {
633 mPersistedFile->closeDataFile();
Yi Jin329130b2018-02-09 16:47:47 -0800634
Joe Onorato99598ee2019-02-11 15:55:13 +0000635 // Set the stored metadata
636 IncidentReportArgs combinedArgs;
637 mBatch->getCombinedPersistedArgs(&combinedArgs);
638 IncidentMetadata persistedMetadata;
639 make_metadata(&persistedMetadata, metadata, mPersistedFile->getTimestampNs(),
Joe Onorato7a406b42019-04-12 18:11:30 -0700640 persistedPrivacyPolicy, combinedArgs);
Joe Onorato99598ee2019-02-11 15:55:13 +0000641 mPersistedFile->setMetadata(persistedMetadata);
Joe Onorato1754d742016-11-21 17:51:35 -0800642
Joe Onorato99598ee2019-02-11 15:55:13 +0000643 mPersistedFile->markCompleted();
644 err = mPersistedFile->saveEnvelope();
645 if (err != NO_ERROR) {
646 ALOGW("mPersistedFile->saveEnvelope returned %s. Won't send broadcast",
647 strerror(-err));
648 // Abandon ship.
649 mWorkDirectory->remove(mPersistedFile);
Joe Onorato1754d742016-11-21 17:51:35 -0800650 }
651 }
652
Joe Onorato99598ee2019-02-11 15:55:13 +0000653 // Write the metadata to the streaming ones
654 mBatch->forEachStreamingRequest([reportId, &metadata](const sp<ReportRequest>& request) {
655 IncidentMetadata streamingMetadata;
656 make_metadata(&streamingMetadata, metadata, reportId,
657 request->args.getPrivacyPolicy(), request);
658 status_t nonFatalErr = write_section(request->getFd(), FIELD_ID_METADATA,
659 streamingMetadata);
660 if (nonFatalErr != NO_ERROR) {
661 ALOGW("Error writing the metadata to streaming incident report. This is the last"
662 " thing so we won't return an error: %s", strerror(nonFatalErr));
Joe Onorato1754d742016-11-21 17:51:35 -0800663 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000664 });
Joe Onorato1754d742016-11-21 17:51:35 -0800665
Joe Onorato99598ee2019-02-11 15:55:13 +0000666 // Finish up the streaming ones.
667 mBatch->forEachStreamingRequest([](const sp<ReportRequest>& request) {
668 request->closeFd();
669 });
670
671 // Tell the listeners that we're done.
672 if (err == NO_ERROR) {
673 mBatch->forEachListener([](const auto& listener) {
674 listener->onReportFinished();
675 });
676 } else {
677 mBatch->forEachListener([](const auto& listener) {
678 listener->onReportFailed();
679 });
Joe Onorato1754d742016-11-21 17:51:35 -0800680 }
681
Joe Onorato99598ee2019-02-11 15:55:13 +0000682 ALOGI("Done taking incident report err=%s", strerror(-err));
Joe Onorato1754d742016-11-21 17:51:35 -0800683}
684
Joe Onorato99598ee2019-02-11 15:55:13 +0000685void Reporter::cancel_and_remove_failed_requests() {
686 // Handle a failure in the persisted file
687 if (mPersistedFile != nullptr) {
688 if (mPersistedFile->getWriteError() != NO_ERROR) {
689 ALOGW("Error writing to the persisted file (%s). Closing it and canceling.",
690 strerror(-mPersistedFile->getWriteError()));
691 mBatch->forEachPersistedRequest([this](const sp<ReportRequest>& request) {
692 sp<IIncidentReportStatusListener> listener = request->getListener();
693 if (listener != nullptr) {
694 listener->onReportFailed();
695 }
696 mBatch->removeRequest(request);
697 });
698 mWriter.setPersistedFile(nullptr);
699 mPersistedFile->closeDataFile();
700 mWorkDirectory->remove(mPersistedFile);
701 mPersistedFile = nullptr;
Joe Onorato1754d742016-11-21 17:51:35 -0800702 }
Joe Onorato1754d742016-11-21 17:51:35 -0800703 }
Joe Onorato1754d742016-11-21 17:51:35 -0800704
Joe Onorato99598ee2019-02-11 15:55:13 +0000705 // Handle failures in the streaming files
706 vector<sp<ReportRequest>> failed;
707 mBatch->getFailedRequests(&failed);
708 for (sp<ReportRequest>& request: failed) {
709 ALOGW("Error writing to a request stream (%s). Closing it and canceling.",
710 strerror(-request->getStatus()));
711 sp<IIncidentReportStatusListener> listener = request->getListener();
712 if (listener != nullptr) {
713 listener->onReportFailed();
714 }
715 request->closeFd(); // Will only close the streaming ones.
716 mBatch->removeRequest(request);
717 }
Joe Onorato1754d742016-11-21 17:51:35 -0800718}
Yi Jin6cacbcb2018-03-30 14:04:52 -0700719
720} // namespace incidentd
721} // namespace os
722} // namespace android