blob: aa40f85fd340ecf201d2b5f8711a0296c4e6fb82 [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();
Joe Onorato99598ee2019-02-11 15:55:13 +0000367}
368
369void ReportWriter::setSectionStats(const FdBuffer& buffer) {
370 mSectionStatsCalledForSectionId = mCurrentSectionId;
371 mDumpSizeBytes = buffer.size();
372 mDumpDurationMs = buffer.durationMs();
373 mSectionTimedOut = buffer.timedOut();
374 mSectionTruncated = buffer.truncated();
375 mSectionBufferSuccess = !buffer.timedOut() && !buffer.truncated();
376}
377
378void ReportWriter::endSection(IncidentMetadata::SectionStats* sectionMetadata) {
379 long endTime = uptimeMillis();
380
381 if (mSectionStatsCalledForSectionId != mCurrentSectionId) {
382 ALOGW("setSectionStats not called for section %d", mCurrentSectionId);
383 }
384
385 sectionMetadata->set_id(mCurrentSectionId);
386 sectionMetadata->set_success((!mHadError) && mSectionBufferSuccess);
387 sectionMetadata->set_report_size_bytes(mMaxSectionDataFilteredSize);
388 sectionMetadata->set_exec_duration_ms(endTime - mSectionStartTimeMs);
389 sectionMetadata->set_dump_size_bytes(mDumpSizeBytes);
390 sectionMetadata->set_dump_duration_ms(mDumpDurationMs);
391 sectionMetadata->set_timed_out(mSectionTimedOut);
392 sectionMetadata->set_is_truncated(mSectionTruncated);
393 sectionMetadata->set_error_msg(mSectionErrors);
394}
395
396void ReportWriter::warning(const Section* section, status_t err, const char* format, ...) {
397 va_list args;
398 va_start(args, format);
399 vflog(section, err, ANDROID_LOG_ERROR, "error", format, args);
400 va_end(args);
401}
402
403void ReportWriter::error(const Section* section, status_t err, const char* format, ...) {
404 va_list args;
405 va_start(args, format);
406 vflog(section, err, ANDROID_LOG_WARN, "warning", format, args);
407 va_end(args);
408}
409
410void ReportWriter::vflog(const Section* section, status_t err, int level, const char* levelText,
411 const char* format, va_list args) {
412 const char* prefixFormat = "%s in section %d (%d) '%s': ";
413 int prefixLen = snprintf(NULL, 0, prefixFormat, levelText, section->id,
414 err, strerror(-err));
415
416 va_list measureArgs;
417 va_copy(measureArgs, args);
418 int messageLen = vsnprintf(NULL, 0, format, args);
419 va_end(measureArgs);
420
421 char* line = (char*)malloc(prefixLen + messageLen + 1);
422 if (line == NULL) {
423 // All hope is lost, just give up.
424 return;
425 }
426
427 sprintf(line, prefixFormat, levelText, section->id, err, strerror(-err));
428
429 vsprintf(line + prefixLen, format, args);
430
431 __android_log_write(level, LOG_TAG, line);
432
433 if (mSectionErrors.length() == 0) {
434 mSectionErrors = line;
435 } else {
436 mSectionErrors += '\n';
437 mSectionErrors += line;
438 }
439
440 free(line);
441
442 if (level >= ANDROID_LOG_ERROR) {
443 mHadError = true;
444 }
445}
446
447// Reads data from FdBuffer and writes it to the requests file descriptor.
448status_t ReportWriter::writeSection(const FdBuffer& buffer) {
449 PrivacyFilter filter(mCurrentSectionId, get_privacy_of_section(mCurrentSectionId));
450
451 // Add the fd for the persisted requests
452 if (mPersistedFile != nullptr) {
453 filter.addFd(new PersistedFilterFd(mMaxPersistedPrivacyPolicy,
454 mPersistedFile->getDataFileFd(), mPersistedFile));
455 }
456
457 // Add the fds for the streamed requests
458 mBatch->forEachStreamingRequest([&filter, this](const sp<ReportRequest>& request) {
Joe Onorato7a406b42019-04-12 18:11:30 -0700459 if (request->ok()
460 && request->args.containsSection(mCurrentSectionId,
461 section_requires_specific_mention(mCurrentSectionId))) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000462 filter.addFd(new StreamingFilterFd(request->args.getPrivacyPolicy(),
463 request->getFd(), request));
464 }
465 });
466
Yao Chena51f3fa2019-04-26 10:30:11 -0700467 return filter.writeData(buffer, PRIVACY_POLICY_LOCAL, &mMaxSectionDataFilteredSize);
Joe Onorato99598ee2019-02-11 15:55:13 +0000468}
469
470
471// ================================================================================
Mike Ma643de922019-12-17 10:56:17 -0800472Reporter::Reporter(const sp<WorkDirectory>& workDirectory,
473 const sp<ReportBatch>& batch,
474 const vector<BringYourOwnSection*>& registeredSections)
Joe Onorato99598ee2019-02-11 15:55:13 +0000475 :mWorkDirectory(workDirectory),
476 mWriter(batch),
Mike Ma643de922019-12-17 10:56:17 -0800477 mBatch(batch),
478 mRegisteredSections(registeredSections) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000479}
480
481Reporter::~Reporter() {
482}
483
484void Reporter::runReport(size_t* reportByteSize) {
Joe Onorato1754d742016-11-21 17:51:35 -0800485 status_t err = NO_ERROR;
Joe Onorato99598ee2019-02-11 15:55:13 +0000486
487 IncidentMetadata metadata;
488 int persistedPrivacyPolicy = PRIVACY_POLICY_UNSET;
Joe Onorato1754d742016-11-21 17:51:35 -0800489
Joe Onorato99598ee2019-02-11 15:55:13 +0000490 (*reportByteSize) = 0;
Joe Onorato1754d742016-11-21 17:51:35 -0800491
492 // Tell everyone that we're starting.
Joe Onorato99598ee2019-02-11 15:55:13 +0000493 ALOGI("Starting incident report");
494 mBatch->forEachListener([](const auto& listener) { listener->onReportStarted(); });
495
496 if (mBatch->hasPersistedReports()) {
497 // Open a work file to contain the contents of all of the persisted reports.
498 // For this block, if we can't initialize the report file for some reason,
499 // then we will remove the persisted ReportRequests from the report, but
500 // continue with the streaming ones.
501 mPersistedFile = mWorkDirectory->createReportFile();
502 ALOGI("Report will be persisted: envelope: %s data: %s",
503 mPersistedFile->getEnvelopeFileName().c_str(),
504 mPersistedFile->getDataFileName().c_str());
505
506 // Record all of the metadata to the persisted file's metadata file.
507 // It will be read from there and reconstructed as the actual reports
508 // are sent out.
509 if (mPersistedFile != nullptr) {
510 mBatch->forEachPersistedRequest([this, &persistedPrivacyPolicy](
511 const sp<ReportRequest>& request) {
512 mPersistedFile->addReport(request->args);
513 if (request->args.getPrivacyPolicy() < persistedPrivacyPolicy) {
514 persistedPrivacyPolicy = request->args.getPrivacyPolicy();
515 }
516 });
517 mPersistedFile->setMaxPersistedPrivacyPolicy(persistedPrivacyPolicy);
518 err = mPersistedFile->saveEnvelope();
519 if (err != NO_ERROR) {
520 mWorkDirectory->remove(mPersistedFile);
521 mPersistedFile = nullptr;
522 }
523 mWriter.setMaxPersistedPrivacyPolicy(persistedPrivacyPolicy);
524 }
525
526 if (mPersistedFile != nullptr) {
527 err = mPersistedFile->startWritingDataFile();
528 if (err != NO_ERROR) {
529 mWorkDirectory->remove(mPersistedFile);
530 mPersistedFile = nullptr;
531 }
532 }
533
534 if (mPersistedFile != nullptr) {
535 mWriter.setPersistedFile(mPersistedFile);
536 } else {
537 ALOGW("Error creating the persisted file, so clearing persisted reports.");
538 // If we couldn't open the file (permissions err, etc), then
539 // we still want to proceed with any streaming reports, but
540 // cancel all of the persisted ones.
541 mBatch->forEachPersistedRequest([](const sp<ReportRequest>& request) {
542 sp<IIncidentReportStatusListener> listener = request->getListener();
543 if (listener != nullptr) {
544 listener->onReportFailed();
545 }
546 });
547 mBatch->clearPersistedRequests();
Joe Onorato1754d742016-11-21 17:51:35 -0800548 }
549 }
550
Joe Onorato99598ee2019-02-11 15:55:13 +0000551 // If we have a persisted ID, then we allow all the readers to see that. There's
552 // enough in the data to allow for a join, and nothing in here that intrisincally
553 // could ever prevent that, so just give them the ID. If we don't have that then we
554 // make and ID that's extremely likely to be unique, but clock resetting could allow
555 // it to be duplicate.
556 int64_t reportId;
557 if (mPersistedFile != nullptr) {
558 reportId = mPersistedFile->getTimestampNs();
559 } else {
560 struct timespec spec;
561 clock_gettime(CLOCK_REALTIME, &spec);
562 reportId = (spec.tv_sec) * 1000 + spec.tv_nsec;
563 }
564
565 // Write the incident report headers - each request gets its own headers. It's different
566 // from the other top-level fields in IncidentReport that are the sections where the rest
567 // is all shared data (although with their own individual privacy filtering).
568 mBatch->forEachStreamingRequest([](const sp<ReportRequest>& request) {
569 const vector<vector<uint8_t>>& headers = request->args.headers();
570 for (vector<vector<uint8_t>>::const_iterator buf = headers.begin(); buf != headers.end();
571 buf++) {
572 // If there was an error now, there will be an error later and we will remove
573 // it from the list then.
Yao Chencbafce92019-04-01 15:56:44 -0700574 write_header_section(request->getFd(), buf->data(), buf->size());
Joe Onorato99598ee2019-02-11 15:55:13 +0000575 }
576 });
577
578 // If writing to any of the headers failed, we don't want to keep processing
579 // sections for it.
580 cancel_and_remove_failed_requests();
Joe Onorato1754d742016-11-21 17:51:35 -0800581
582 // For each of the report fields, see if we need it, and if so, execute the command
583 // and report to those that care that we're doing it.
Yi Jinb592e3b2018-02-01 15:17:04 -0800584 for (const Section** section = SECTION_LIST; *section; section++) {
Mike Ma643de922019-12-17 10:56:17 -0800585 if (execute_section(*section, &metadata, reportByteSize) != NO_ERROR) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000586 goto DONE;
587 }
Mike Ma643de922019-12-17 10:56:17 -0800588 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000589
Mike Ma643de922019-12-17 10:56:17 -0800590 for (const Section* section : mRegisteredSections) {
591 if (execute_section(section, &metadata, reportByteSize) != NO_ERROR) {
592 goto DONE;
593 }
Joe Onorato1754d742016-11-21 17:51:35 -0800594 }
595
Yi Jinedfd5bb2017-09-06 17:09:11 -0700596DONE:
Joe Onorato99598ee2019-02-11 15:55:13 +0000597 // Finish up the persisted file.
598 if (mPersistedFile != nullptr) {
599 mPersistedFile->closeDataFile();
Yi Jin329130b2018-02-09 16:47:47 -0800600
Joe Onorato99598ee2019-02-11 15:55:13 +0000601 // Set the stored metadata
602 IncidentReportArgs combinedArgs;
603 mBatch->getCombinedPersistedArgs(&combinedArgs);
604 IncidentMetadata persistedMetadata;
605 make_metadata(&persistedMetadata, metadata, mPersistedFile->getTimestampNs(),
Joe Onorato7a406b42019-04-12 18:11:30 -0700606 persistedPrivacyPolicy, combinedArgs);
Joe Onorato99598ee2019-02-11 15:55:13 +0000607 mPersistedFile->setMetadata(persistedMetadata);
Joe Onorato1754d742016-11-21 17:51:35 -0800608
Joe Onorato99598ee2019-02-11 15:55:13 +0000609 mPersistedFile->markCompleted();
610 err = mPersistedFile->saveEnvelope();
611 if (err != NO_ERROR) {
612 ALOGW("mPersistedFile->saveEnvelope returned %s. Won't send broadcast",
613 strerror(-err));
614 // Abandon ship.
615 mWorkDirectory->remove(mPersistedFile);
Joe Onorato1754d742016-11-21 17:51:35 -0800616 }
617 }
618
Joe Onorato99598ee2019-02-11 15:55:13 +0000619 // Write the metadata to the streaming ones
620 mBatch->forEachStreamingRequest([reportId, &metadata](const sp<ReportRequest>& request) {
621 IncidentMetadata streamingMetadata;
622 make_metadata(&streamingMetadata, metadata, reportId,
623 request->args.getPrivacyPolicy(), request);
624 status_t nonFatalErr = write_section(request->getFd(), FIELD_ID_METADATA,
625 streamingMetadata);
626 if (nonFatalErr != NO_ERROR) {
627 ALOGW("Error writing the metadata to streaming incident report. This is the last"
628 " thing so we won't return an error: %s", strerror(nonFatalErr));
Joe Onorato1754d742016-11-21 17:51:35 -0800629 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000630 });
Joe Onorato1754d742016-11-21 17:51:35 -0800631
Joe Onorato99598ee2019-02-11 15:55:13 +0000632 // Finish up the streaming ones.
633 mBatch->forEachStreamingRequest([](const sp<ReportRequest>& request) {
634 request->closeFd();
635 });
636
637 // Tell the listeners that we're done.
638 if (err == NO_ERROR) {
639 mBatch->forEachListener([](const auto& listener) {
640 listener->onReportFinished();
641 });
642 } else {
643 mBatch->forEachListener([](const auto& listener) {
644 listener->onReportFailed();
645 });
Joe Onorato1754d742016-11-21 17:51:35 -0800646 }
647
Joe Onorato99598ee2019-02-11 15:55:13 +0000648 ALOGI("Done taking incident report err=%s", strerror(-err));
Joe Onorato1754d742016-11-21 17:51:35 -0800649}
650
Mike Ma643de922019-12-17 10:56:17 -0800651status_t Reporter::execute_section(const Section* section, IncidentMetadata* metadata,
652 size_t* reportByteSize) {
653 const int sectionId = section->id;
654
655 // If nobody wants this section, skip it.
656 if (!mBatch->containsSection(sectionId)) {
657 return NO_ERROR;
658 }
659
660 ALOGD("Start incident report section %d '%s'", sectionId, section->name.string());
661 IncidentMetadata::SectionStats* sectionMetadata = metadata->add_sections();
662
663 // Notify listener of starting
664 mBatch->forEachListener(sectionId, [sectionId](const auto& listener) {
665 listener->onReportSectionStatus(
666 sectionId, IIncidentReportStatusListener::STATUS_STARTING);
667 });
668
669 // Go get the data and write it into the file descriptors.
670 mWriter.startSection(sectionId);
671 status_t err = section->Execute(&mWriter);
672 mWriter.endSection(sectionMetadata);
673
674 // Sections returning errors are fatal. Most errors should not be fatal.
675 if (err != NO_ERROR) {
676 mWriter.error(section, err, "Section failed. Stopping report.");
677 return err;
678 }
679
680 // The returned max data size is used for throttling too many incident reports.
681 (*reportByteSize) += sectionMetadata->report_size_bytes();
682
683 // For any requests that failed during this section, remove them now. We do this
684 // before calling back about section finished, so listeners do not erroniously get the
685 // impression that the section succeeded. But we do it here instead of inside
686 // writeSection so that the callback is done from a known context and not from the
687 // bowels of a section, where changing the batch could cause odd errors.
688 cancel_and_remove_failed_requests();
689
690 // Notify listener of finishing
691 mBatch->forEachListener(sectionId, [sectionId](const auto& listener) {
692 listener->onReportSectionStatus(
693 sectionId, IIncidentReportStatusListener::STATUS_FINISHED);
694 });
695
696 ALOGD("Finish incident report section %d '%s'", sectionId, section->name.string());
697 return NO_ERROR;
698}
699
Joe Onorato99598ee2019-02-11 15:55:13 +0000700void Reporter::cancel_and_remove_failed_requests() {
701 // Handle a failure in the persisted file
702 if (mPersistedFile != nullptr) {
703 if (mPersistedFile->getWriteError() != NO_ERROR) {
704 ALOGW("Error writing to the persisted file (%s). Closing it and canceling.",
705 strerror(-mPersistedFile->getWriteError()));
706 mBatch->forEachPersistedRequest([this](const sp<ReportRequest>& request) {
707 sp<IIncidentReportStatusListener> listener = request->getListener();
708 if (listener != nullptr) {
709 listener->onReportFailed();
710 }
711 mBatch->removeRequest(request);
712 });
713 mWriter.setPersistedFile(nullptr);
714 mPersistedFile->closeDataFile();
715 mWorkDirectory->remove(mPersistedFile);
716 mPersistedFile = nullptr;
Joe Onorato1754d742016-11-21 17:51:35 -0800717 }
Joe Onorato1754d742016-11-21 17:51:35 -0800718 }
Joe Onorato1754d742016-11-21 17:51:35 -0800719
Joe Onorato99598ee2019-02-11 15:55:13 +0000720 // Handle failures in the streaming files
721 vector<sp<ReportRequest>> failed;
722 mBatch->getFailedRequests(&failed);
723 for (sp<ReportRequest>& request: failed) {
724 ALOGW("Error writing to a request stream (%s). Closing it and canceling.",
725 strerror(-request->getStatus()));
726 sp<IIncidentReportStatusListener> listener = request->getListener();
727 if (listener != nullptr) {
728 listener->onReportFailed();
729 }
730 request->closeFd(); // Will only close the streaming ones.
731 mBatch->removeRequest(request);
732 }
Joe Onorato1754d742016-11-21 17:51:35 -0800733}
Yi Jin6cacbcb2018-03-30 14:04:52 -0700734
735} // namespace incidentd
736} // namespace os
737} // namespace android