blob: 218c1b27fdccbd2764585139ad4116f98d62c889 [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
69void poo_make_metadata(IncidentMetadata* result, const IncidentMetadata& full,
70 int64_t reportId, int32_t privacyPolicy, const IncidentReportArgs& args) {
71 result->set_report_id(reportId);
72 result->set_dest(privacy_policy_to_dest(privacyPolicy));
73
74 size_t sectionCount = full.sections_size();
75 for (int sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++) {
76 const IncidentMetadata::SectionStats& sectionStats = full.sections(sectionIndex);
77 if (args.containsSection(sectionStats.id())) {
78 *result->add_sections() = sectionStats;
79 }
80 }
81}
82
83// ARGS must have a containsSection(int) method
84template <typename ARGS> 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 (args->containsSection(sectionStats.id())) {
93 *result->add_sections() = sectionStats;
94 }
95 }
96}
97
98// ================================================================================
99class StreamingFilterFd : public FilterFd {
100public:
101 StreamingFilterFd(uint8_t privacyPolicy, int fd, const sp<ReportRequest>& request);
102
103 virtual void onWriteError(status_t err);
104
105private:
106 sp<ReportRequest> mRequest;
107};
108
109StreamingFilterFd::StreamingFilterFd(uint8_t privacyPolicy, int fd,
110 const sp<ReportRequest>& request)
111 :FilterFd(privacyPolicy, fd),
112 mRequest(request) {
113}
114
115void StreamingFilterFd::onWriteError(status_t err) {
116 mRequest->setStatus(err);
117}
118
119
120// ================================================================================
121class PersistedFilterFd : public FilterFd {
122public:
123 PersistedFilterFd(uint8_t privacyPolicy, int fd, const sp<ReportFile>& reportFile);
124
125 virtual void onWriteError(status_t err);
126
127private:
128 sp<ReportFile> mReportFile;
129};
130
131PersistedFilterFd::PersistedFilterFd(uint8_t privacyPolicy, int fd,
132 const sp<ReportFile>& reportFile)
133 :FilterFd(privacyPolicy, fd),
134 mReportFile(reportFile) {
135}
136
137void PersistedFilterFd::onWriteError(status_t err) {
138 mReportFile->setWriteError(err);
139}
140
141
Yi Jin0a3406f2017-06-22 19:23:11 -0700142// ================================================================================
Joe Onorato1754d742016-11-21 17:51:35 -0800143ReportRequest::ReportRequest(const IncidentReportArgs& a,
Joe Onorato99598ee2019-02-11 15:55:13 +0000144 const sp<IIncidentReportStatusListener>& listener, int fd)
145 :args(a),
146 mListener(listener),
147 mFd(fd),
148 mIsStreaming(fd >= 0),
149 mStatus(NO_ERROR) {
150}
Joe Onorato1754d742016-11-21 17:51:35 -0800151
Yi Jinb592e3b2018-02-01 15:17:04 -0800152ReportRequest::~ReportRequest() {
Joe Onorato99598ee2019-02-11 15:55:13 +0000153 if (mIsStreaming && mFd >= 0) {
Yi Jin22769e02017-10-16 14:42:50 -0700154 // clean up the opened file descriptor
Joe Onorato99598ee2019-02-11 15:55:13 +0000155 close(mFd);
Yi Jin22769e02017-10-16 14:42:50 -0700156 }
Joe Onorato1754d742016-11-21 17:51:35 -0800157}
158
Joe Onorato99598ee2019-02-11 15:55:13 +0000159bool ReportRequest::ok() {
160 return mFd >= 0 && mStatus == NO_ERROR;
Joe Onorato1754d742016-11-21 17:51:35 -0800161}
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
289void ReportBatch::getFailedRequests(vector<sp<ReportRequest>>* requests) {
290 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
291 it != mPersistedRequests.end(); it++) {
292 if (it->second->getStatus() != NO_ERROR) {
293 requests->push_back(it->second);
294 }
295 }
296 for (vector<sp<ReportRequest>>::iterator request = mStreamingRequests.begin();
297 request != mStreamingRequests.end(); request++) {
298 if ((*request)->getStatus() != NO_ERROR) {
299 requests->push_back(*request);
300 }
301 }
302}
303
304void ReportBatch::removeRequest(const sp<ReportRequest>& request) {
305 for (map<ComponentName, sp<ReportRequest>>::iterator it = mPersistedRequests.begin();
306 it != mPersistedRequests.end(); it++) {
307 if (it->second == request) {
308 mPersistedRequests.erase(it);
309 return;
310 }
311 }
312 for (vector<sp<ReportRequest>>::iterator it = mStreamingRequests.begin();
313 it != mStreamingRequests.end(); it++) {
314 if (*it == request) {
315 mStreamingRequests.erase(it);
316 return;
317 }
318 }
319}
320
321// ================================================================================
322ReportWriter::ReportWriter(const sp<ReportBatch>& batch)
323 :mBatch(batch),
324 mPersistedFile(),
325 mMaxPersistedPrivacyPolicy(PRIVACY_POLICY_UNSET) {
326}
327
328ReportWriter::~ReportWriter() {
329}
330
331void ReportWriter::setPersistedFile(sp<ReportFile> file) {
332 mPersistedFile = file;
333}
334
335void ReportWriter::setMaxPersistedPrivacyPolicy(uint8_t privacyPolicy) {
336 mMaxPersistedPrivacyPolicy = privacyPolicy;
337}
338
339void ReportWriter::startSection(int sectionId) {
340 mCurrentSectionId = sectionId;
341 mSectionStartTimeMs = uptimeMillis();
342
343 mSectionStatsCalledForSectionId = -1;
344 mDumpSizeBytes = 0;
345 mDumpDurationMs = 0;
346 mSectionTimedOut = false;
347 mSectionTruncated = false;
348 mSectionBufferSuccess = false;
349 mHadError = false;
350 mSectionErrors.clear();
351
352}
353
354void ReportWriter::setSectionStats(const FdBuffer& buffer) {
355 mSectionStatsCalledForSectionId = mCurrentSectionId;
356 mDumpSizeBytes = buffer.size();
357 mDumpDurationMs = buffer.durationMs();
358 mSectionTimedOut = buffer.timedOut();
359 mSectionTruncated = buffer.truncated();
360 mSectionBufferSuccess = !buffer.timedOut() && !buffer.truncated();
361}
362
363void ReportWriter::endSection(IncidentMetadata::SectionStats* sectionMetadata) {
364 long endTime = uptimeMillis();
365
366 if (mSectionStatsCalledForSectionId != mCurrentSectionId) {
367 ALOGW("setSectionStats not called for section %d", mCurrentSectionId);
368 }
369
370 sectionMetadata->set_id(mCurrentSectionId);
371 sectionMetadata->set_success((!mHadError) && mSectionBufferSuccess);
372 sectionMetadata->set_report_size_bytes(mMaxSectionDataFilteredSize);
373 sectionMetadata->set_exec_duration_ms(endTime - mSectionStartTimeMs);
374 sectionMetadata->set_dump_size_bytes(mDumpSizeBytes);
375 sectionMetadata->set_dump_duration_ms(mDumpDurationMs);
376 sectionMetadata->set_timed_out(mSectionTimedOut);
377 sectionMetadata->set_is_truncated(mSectionTruncated);
378 sectionMetadata->set_error_msg(mSectionErrors);
379}
380
381void ReportWriter::warning(const Section* section, status_t err, const char* format, ...) {
382 va_list args;
383 va_start(args, format);
384 vflog(section, err, ANDROID_LOG_ERROR, "error", format, args);
385 va_end(args);
386}
387
388void ReportWriter::error(const Section* section, status_t err, const char* format, ...) {
389 va_list args;
390 va_start(args, format);
391 vflog(section, err, ANDROID_LOG_WARN, "warning", format, args);
392 va_end(args);
393}
394
395void ReportWriter::vflog(const Section* section, status_t err, int level, const char* levelText,
396 const char* format, va_list args) {
397 const char* prefixFormat = "%s in section %d (%d) '%s': ";
398 int prefixLen = snprintf(NULL, 0, prefixFormat, levelText, section->id,
399 err, strerror(-err));
400
401 va_list measureArgs;
402 va_copy(measureArgs, args);
403 int messageLen = vsnprintf(NULL, 0, format, args);
404 va_end(measureArgs);
405
406 char* line = (char*)malloc(prefixLen + messageLen + 1);
407 if (line == NULL) {
408 // All hope is lost, just give up.
409 return;
410 }
411
412 sprintf(line, prefixFormat, levelText, section->id, err, strerror(-err));
413
414 vsprintf(line + prefixLen, format, args);
415
416 __android_log_write(level, LOG_TAG, line);
417
418 if (mSectionErrors.length() == 0) {
419 mSectionErrors = line;
420 } else {
421 mSectionErrors += '\n';
422 mSectionErrors += line;
423 }
424
425 free(line);
426
427 if (level >= ANDROID_LOG_ERROR) {
428 mHadError = true;
429 }
430}
431
432// Reads data from FdBuffer and writes it to the requests file descriptor.
433status_t ReportWriter::writeSection(const FdBuffer& buffer) {
434 PrivacyFilter filter(mCurrentSectionId, get_privacy_of_section(mCurrentSectionId));
435
436 // Add the fd for the persisted requests
437 if (mPersistedFile != nullptr) {
438 filter.addFd(new PersistedFilterFd(mMaxPersistedPrivacyPolicy,
439 mPersistedFile->getDataFileFd(), mPersistedFile));
440 }
441
442 // Add the fds for the streamed requests
443 mBatch->forEachStreamingRequest([&filter, this](const sp<ReportRequest>& request) {
444 if (request->ok() && request->args.containsSection(mCurrentSectionId)) {
445 filter.addFd(new StreamingFilterFd(request->args.getPrivacyPolicy(),
446 request->getFd(), request));
447 }
448 });
449
450 return filter.writeData(buffer, PRIVACY_POLICY_LOCAL, &mMaxSectionDataFilteredSize);
451}
452
453
454// ================================================================================
455Reporter::Reporter(const sp<WorkDirectory>& workDirectory, const sp<ReportBatch>& batch)
456 :mWorkDirectory(workDirectory),
457 mWriter(batch),
458 mBatch(batch) {
459}
460
461Reporter::~Reporter() {
462}
463
464void Reporter::runReport(size_t* reportByteSize) {
Joe Onorato1754d742016-11-21 17:51:35 -0800465 status_t err = NO_ERROR;
Joe Onorato99598ee2019-02-11 15:55:13 +0000466
467 IncidentMetadata metadata;
468 int persistedPrivacyPolicy = PRIVACY_POLICY_UNSET;
Joe Onorato1754d742016-11-21 17:51:35 -0800469
Joe Onorato99598ee2019-02-11 15:55:13 +0000470 (*reportByteSize) = 0;
Joe Onorato1754d742016-11-21 17:51:35 -0800471
472 // Tell everyone that we're starting.
Joe Onorato99598ee2019-02-11 15:55:13 +0000473 ALOGI("Starting incident report");
474 mBatch->forEachListener([](const auto& listener) { listener->onReportStarted(); });
475
476 if (mBatch->hasPersistedReports()) {
477 // Open a work file to contain the contents of all of the persisted reports.
478 // For this block, if we can't initialize the report file for some reason,
479 // then we will remove the persisted ReportRequests from the report, but
480 // continue with the streaming ones.
481 mPersistedFile = mWorkDirectory->createReportFile();
482 ALOGI("Report will be persisted: envelope: %s data: %s",
483 mPersistedFile->getEnvelopeFileName().c_str(),
484 mPersistedFile->getDataFileName().c_str());
485
486 // Record all of the metadata to the persisted file's metadata file.
487 // It will be read from there and reconstructed as the actual reports
488 // are sent out.
489 if (mPersistedFile != nullptr) {
490 mBatch->forEachPersistedRequest([this, &persistedPrivacyPolicy](
491 const sp<ReportRequest>& request) {
492 mPersistedFile->addReport(request->args);
493 if (request->args.getPrivacyPolicy() < persistedPrivacyPolicy) {
494 persistedPrivacyPolicy = request->args.getPrivacyPolicy();
495 }
496 });
497 mPersistedFile->setMaxPersistedPrivacyPolicy(persistedPrivacyPolicy);
498 err = mPersistedFile->saveEnvelope();
499 if (err != NO_ERROR) {
500 mWorkDirectory->remove(mPersistedFile);
501 mPersistedFile = nullptr;
502 }
503 mWriter.setMaxPersistedPrivacyPolicy(persistedPrivacyPolicy);
504 }
505
506 if (mPersistedFile != nullptr) {
507 err = mPersistedFile->startWritingDataFile();
508 if (err != NO_ERROR) {
509 mWorkDirectory->remove(mPersistedFile);
510 mPersistedFile = nullptr;
511 }
512 }
513
514 if (mPersistedFile != nullptr) {
515 mWriter.setPersistedFile(mPersistedFile);
516 } else {
517 ALOGW("Error creating the persisted file, so clearing persisted reports.");
518 // If we couldn't open the file (permissions err, etc), then
519 // we still want to proceed with any streaming reports, but
520 // cancel all of the persisted ones.
521 mBatch->forEachPersistedRequest([](const sp<ReportRequest>& request) {
522 sp<IIncidentReportStatusListener> listener = request->getListener();
523 if (listener != nullptr) {
524 listener->onReportFailed();
525 }
526 });
527 mBatch->clearPersistedRequests();
Joe Onorato1754d742016-11-21 17:51:35 -0800528 }
529 }
530
Joe Onorato99598ee2019-02-11 15:55:13 +0000531 // If we have a persisted ID, then we allow all the readers to see that. There's
532 // enough in the data to allow for a join, and nothing in here that intrisincally
533 // could ever prevent that, so just give them the ID. If we don't have that then we
534 // make and ID that's extremely likely to be unique, but clock resetting could allow
535 // it to be duplicate.
536 int64_t reportId;
537 if (mPersistedFile != nullptr) {
538 reportId = mPersistedFile->getTimestampNs();
539 } else {
540 struct timespec spec;
541 clock_gettime(CLOCK_REALTIME, &spec);
542 reportId = (spec.tv_sec) * 1000 + spec.tv_nsec;
543 }
544
545 // Write the incident report headers - each request gets its own headers. It's different
546 // from the other top-level fields in IncidentReport that are the sections where the rest
547 // is all shared data (although with their own individual privacy filtering).
548 mBatch->forEachStreamingRequest([](const sp<ReportRequest>& request) {
549 const vector<vector<uint8_t>>& headers = request->args.headers();
550 for (vector<vector<uint8_t>>::const_iterator buf = headers.begin(); buf != headers.end();
551 buf++) {
552 // If there was an error now, there will be an error later and we will remove
553 // it from the list then.
Yao Chencbafce92019-04-01 15:56:44 -0700554 write_header_section(request->getFd(), buf->data(), buf->size());
Joe Onorato99598ee2019-02-11 15:55:13 +0000555 }
556 });
557
558 // If writing to any of the headers failed, we don't want to keep processing
559 // sections for it.
560 cancel_and_remove_failed_requests();
Joe Onorato1754d742016-11-21 17:51:35 -0800561
562 // For each of the report fields, see if we need it, and if so, execute the command
563 // and report to those that care that we're doing it.
Yi Jinb592e3b2018-02-01 15:17:04 -0800564 for (const Section** section = SECTION_LIST; *section; section++) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000565 const int sectionId = (*section)->id;
566
Joe Onorato99598ee2019-02-11 15:55:13 +0000567 // If nobody wants this section, skip it.
568 if (!mBatch->containsSection(sectionId)) {
569 continue;
Joe Onorato1754d742016-11-21 17:51:35 -0800570 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000571
572 ALOGD("Start incident report section %d '%s'", sectionId, (*section)->name.string());
573 IncidentMetadata::SectionStats* sectionMetadata = metadata.add_sections();
574
575 // Notify listener of starting
576 mBatch->forEachListener(sectionId, [sectionId](const auto& listener) {
577 listener->onReportSectionStatus(
578 sectionId, IIncidentReportStatusListener::STATUS_STARTING);
579 });
580
581 // Go get the data and write it into the file descriptors.
582 mWriter.startSection(sectionId);
583 err = (*section)->Execute(&mWriter);
584 mWriter.endSection(sectionMetadata);
585
586 // Sections returning errors are fatal. Most errors should not be fatal.
587 if (err != NO_ERROR) {
588 mWriter.error((*section), err, "Section failed. Stopping report.");
589 goto DONE;
590 }
591
592 // The returned max data size is used for throttling too many incident reports.
593 (*reportByteSize) += sectionMetadata->report_size_bytes();
594
595 // For any requests that failed during this section, remove them now. We do this
596 // before calling back about section finished, so listeners do not erroniously get the
597 // impression that the section succeeded. But we do it here instead of inside
598 // writeSection so that the callback is done from a known context and not from the
599 // bowels of a section, where changing the batch could cause odd errors.
600 cancel_and_remove_failed_requests();
601
602 // Notify listener of finishing
603 mBatch->forEachListener(sectionId, [sectionId](const auto& listener) {
604 listener->onReportSectionStatus(
605 sectionId, IIncidentReportStatusListener::STATUS_FINISHED);
606 });
607
608 ALOGD("Finish incident report section %d '%s'", sectionId, (*section)->name.string());
Joe Onorato1754d742016-11-21 17:51:35 -0800609 }
610
Yi Jinedfd5bb2017-09-06 17:09:11 -0700611DONE:
Joe Onorato99598ee2019-02-11 15:55:13 +0000612 // Finish up the persisted file.
613 if (mPersistedFile != nullptr) {
614 mPersistedFile->closeDataFile();
Yi Jin329130b2018-02-09 16:47:47 -0800615
Joe Onorato99598ee2019-02-11 15:55:13 +0000616 // Set the stored metadata
617 IncidentReportArgs combinedArgs;
618 mBatch->getCombinedPersistedArgs(&combinedArgs);
619 IncidentMetadata persistedMetadata;
620 make_metadata(&persistedMetadata, metadata, mPersistedFile->getTimestampNs(),
621 persistedPrivacyPolicy, &combinedArgs);
622 mPersistedFile->setMetadata(persistedMetadata);
Joe Onorato1754d742016-11-21 17:51:35 -0800623
Joe Onorato99598ee2019-02-11 15:55:13 +0000624 mPersistedFile->markCompleted();
625 err = mPersistedFile->saveEnvelope();
626 if (err != NO_ERROR) {
627 ALOGW("mPersistedFile->saveEnvelope returned %s. Won't send broadcast",
628 strerror(-err));
629 // Abandon ship.
630 mWorkDirectory->remove(mPersistedFile);
Joe Onorato1754d742016-11-21 17:51:35 -0800631 }
632 }
633
Joe Onorato99598ee2019-02-11 15:55:13 +0000634 // Write the metadata to the streaming ones
635 mBatch->forEachStreamingRequest([reportId, &metadata](const sp<ReportRequest>& request) {
636 IncidentMetadata streamingMetadata;
637 make_metadata(&streamingMetadata, metadata, reportId,
638 request->args.getPrivacyPolicy(), request);
639 status_t nonFatalErr = write_section(request->getFd(), FIELD_ID_METADATA,
640 streamingMetadata);
641 if (nonFatalErr != NO_ERROR) {
642 ALOGW("Error writing the metadata to streaming incident report. This is the last"
643 " thing so we won't return an error: %s", strerror(nonFatalErr));
Joe Onorato1754d742016-11-21 17:51:35 -0800644 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000645 });
Joe Onorato1754d742016-11-21 17:51:35 -0800646
Joe Onorato99598ee2019-02-11 15:55:13 +0000647 // Finish up the streaming ones.
648 mBatch->forEachStreamingRequest([](const sp<ReportRequest>& request) {
649 request->closeFd();
650 });
651
652 // Tell the listeners that we're done.
653 if (err == NO_ERROR) {
654 mBatch->forEachListener([](const auto& listener) {
655 listener->onReportFinished();
656 });
657 } else {
658 mBatch->forEachListener([](const auto& listener) {
659 listener->onReportFailed();
660 });
Joe Onorato1754d742016-11-21 17:51:35 -0800661 }
662
Joe Onorato99598ee2019-02-11 15:55:13 +0000663 ALOGI("Done taking incident report err=%s", strerror(-err));
Joe Onorato1754d742016-11-21 17:51:35 -0800664}
665
Joe Onorato99598ee2019-02-11 15:55:13 +0000666void Reporter::cancel_and_remove_failed_requests() {
667 // Handle a failure in the persisted file
668 if (mPersistedFile != nullptr) {
669 if (mPersistedFile->getWriteError() != NO_ERROR) {
670 ALOGW("Error writing to the persisted file (%s). Closing it and canceling.",
671 strerror(-mPersistedFile->getWriteError()));
672 mBatch->forEachPersistedRequest([this](const sp<ReportRequest>& request) {
673 sp<IIncidentReportStatusListener> listener = request->getListener();
674 if (listener != nullptr) {
675 listener->onReportFailed();
676 }
677 mBatch->removeRequest(request);
678 });
679 mWriter.setPersistedFile(nullptr);
680 mPersistedFile->closeDataFile();
681 mWorkDirectory->remove(mPersistedFile);
682 mPersistedFile = nullptr;
Joe Onorato1754d742016-11-21 17:51:35 -0800683 }
Joe Onorato1754d742016-11-21 17:51:35 -0800684 }
Joe Onorato1754d742016-11-21 17:51:35 -0800685
Joe Onorato99598ee2019-02-11 15:55:13 +0000686 // Handle failures in the streaming files
687 vector<sp<ReportRequest>> failed;
688 mBatch->getFailedRequests(&failed);
689 for (sp<ReportRequest>& request: failed) {
690 ALOGW("Error writing to a request stream (%s). Closing it and canceling.",
691 strerror(-request->getStatus()));
692 sp<IIncidentReportStatusListener> listener = request->getListener();
693 if (listener != nullptr) {
694 listener->onReportFailed();
695 }
696 request->closeFd(); // Will only close the streaming ones.
697 mBatch->removeRequest(request);
698 }
Joe Onorato1754d742016-11-21 17:51:35 -0800699}
Yi Jin6cacbcb2018-03-30 14:04:52 -0700700
701} // namespace incidentd
702} // namespace os
703} // namespace android