blob: 86a78f095f52c0cf0bef5cca059ae4ad40d3a999 [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>
Mike Mab6f7c472020-03-03 17:58:35 -080038#include <sys/prctl.h>
Yi Jinb592e3b2018-02-01 15:17:04 -080039#include <sys/stat.h>
40#include <sys/types.h>
Kweku Adams3d160912018-05-07 11:26:27 -070041#include <string>
Joe Onorato99598ee2019-02-11 15:55:13 +000042#include <time.h>
Mike Mab6f7c472020-03-03 17:58:35 -080043#include <wait.h>
Joe Onorato1754d742016-11-21 17:51:35 -080044
Yi Jin6cacbcb2018-03-30 14:04:52 -070045namespace android {
46namespace os {
47namespace incidentd {
48
Joe Onorato99598ee2019-02-11 15:55:13 +000049using namespace android::util;
50
51/**
52 * The field id of the metadata section from
53 * frameworks/base/core/proto/android/os/incident.proto
54 */
55const int FIELD_ID_METADATA = 2;
Mike Mab6f7c472020-03-03 17:58:35 -080056// Args for exec gzip
57static const char* GZIP[] = {"/system/bin/gzip", NULL};
Joe Onorato99598ee2019-02-11 15:55:13 +000058
59IncidentMetadata_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
Joe Onorato99598ee2019-02-11 15:55:13 +000073
Joe Onorato7a406b42019-04-12 18:11:30 -070074static bool contains_section(const IncidentReportArgs& args, int sectionId) {
75 return args.containsSection(sectionId, section_requires_specific_mention(sectionId));
76}
77
78static bool contains_section(const sp<ReportRequest>& args, int sectionId) {
79 return args->containsSection(sectionId);
Joe Onorato99598ee2019-02-11 15:55:13 +000080}
81
82// ARGS must have a containsSection(int) method
Joe Onorato7a406b42019-04-12 18:11:30 -070083template <typename ARGS>
84void make_metadata(IncidentMetadata* result, const IncidentMetadata& full,
Joe Onorato99598ee2019-02-11 15:55:13 +000085 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);
Joe Onorato7a406b42019-04-12 18:11:30 -070092 if (contains_section(args, sectionStats.id())) {
Joe Onorato99598ee2019-02-11 15:55:13 +000093 *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),
Mike Mab6f7c472020-03-03 17:58:35 -0800149 mStatus(OK),
150 mZipPid(-1) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000151}
Joe Onorato1754d742016-11-21 17:51:35 -0800152
Yi Jinb592e3b2018-02-01 15:17:04 -0800153ReportRequest::~ReportRequest() {
Joe Onorato99598ee2019-02-11 15:55:13 +0000154 if (mIsStreaming && mFd >= 0) {
Yi Jin22769e02017-10-16 14:42:50 -0700155 // clean up the opened file descriptor
Joe Onorato99598ee2019-02-11 15:55:13 +0000156 close(mFd);
Yi Jin22769e02017-10-16 14:42:50 -0700157 }
Joe Onorato1754d742016-11-21 17:51:35 -0800158}
159
Joe Onorato99598ee2019-02-11 15:55:13 +0000160bool ReportRequest::ok() {
Mike Mab6f7c472020-03-03 17:58:35 -0800161 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;
Joe Onorato1754d742016-11-21 17:51:35 -0800169}
170
Joe Onorato7a406b42019-04-12 18:11:30 -0700171bool ReportRequest::containsSection(int sectionId) const {
172 return args.containsSection(sectionId, section_requires_specific_mention(sectionId));
173}
174
Joe Onorato99598ee2019-02-11 15:55:13 +0000175void ReportRequest::closeFd() {
Mike Mab6f7c472020-03-03 17:58:35 -0800176 if (!mIsStreaming) {
177 return;
178 }
179 if (mFd >= 0) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000180 close(mFd);
181 mFd = -1;
Yi Jin329130b2018-02-09 16:47:47 -0800182 }
Mike Mab6f7c472020-03-03 17:58:35 -0800183 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
193int ReportRequest::getFd() {
194 return mZipPid > 0 ? mZipPipe.writeFd().get() : mFd;
195}
196
197status_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;
Yi Jin3ec5cc72018-01-26 13:42:43 -0800215}
216
Joe Onorato1754d742016-11-21 17:51:35 -0800217// ================================================================================
Joe Onorato99598ee2019-02-11 15:55:13 +0000218ReportBatch::ReportBatch() {}
Yi Jinadd11e92017-07-30 16:10:07 -0700219
Joe Onorato99598ee2019-02-11 15:55:13 +0000220ReportBatch::~ReportBatch() {}
Joe Onorato1754d742016-11-21 17:51:35 -0800221
Joe Onorato99598ee2019-02-11 15:55:13 +0000222void 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 }
Joe Onorato1754d742016-11-21 17:51:35 -0800233}
234
Joe Onorato99598ee2019-02-11 15:55:13 +0000235void ReportBatch::addStreamingReport(const IncidentReportArgs& args,
236 const sp<IIncidentReportStatusListener>& listener, int streamFd) {
237 mStreamingRequests.push_back(new ReportRequest(args, listener, streamFd));
238}
Joe Onorato1754d742016-11-21 17:51:35 -0800239
Joe Onorato99598ee2019-02-11 15:55:13 +0000240bool ReportBatch::empty() const {
241 return mPersistedRequests.size() == 0 && mStreamingRequests.size() == 0;
242}
243
244sp<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
253void 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
260void 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
267void 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
285void 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
307void 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
314bool 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
332void ReportBatch::clearPersistedRequests() {
333 mPersistedRequests.clear();
334}
335
Joe Onoratoe5472052019-04-24 16:27:33 -0700336void 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
344void 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
Joe Onorato99598ee2019-02-11 15:55:13 +0000352void 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
367void 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// ================================================================================
385ReportWriter::ReportWriter(const sp<ReportBatch>& batch)
386 :mBatch(batch),
387 mPersistedFile(),
388 mMaxPersistedPrivacyPolicy(PRIVACY_POLICY_UNSET) {
389}
390
391ReportWriter::~ReportWriter() {
392}
393
394void ReportWriter::setPersistedFile(sp<ReportFile> file) {
395 mPersistedFile = file;
396}
397
398void ReportWriter::setMaxPersistedPrivacyPolicy(uint8_t privacyPolicy) {
399 mMaxPersistedPrivacyPolicy = privacyPolicy;
400}
401
402void 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();
Joe Onorato99598ee2019-02-11 15:55:13 +0000414}
415
416void 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
425void 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
443void 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
450void 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
457void 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.
495status_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) {
Joe Onorato7a406b42019-04-12 18:11:30 -0700506 if (request->ok()
507 && request->args.containsSection(mCurrentSectionId,
508 section_requires_specific_mention(mCurrentSectionId))) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000509 filter.addFd(new StreamingFilterFd(request->args.getPrivacyPolicy(),
510 request->getFd(), request));
511 }
512 });
513
Yao Chena51f3fa2019-04-26 10:30:11 -0700514 return filter.writeData(buffer, PRIVACY_POLICY_LOCAL, &mMaxSectionDataFilteredSize);
Joe Onorato99598ee2019-02-11 15:55:13 +0000515}
516
517
518// ================================================================================
Mike Ma643de922019-12-17 10:56:17 -0800519Reporter::Reporter(const sp<WorkDirectory>& workDirectory,
520 const sp<ReportBatch>& batch,
521 const vector<BringYourOwnSection*>& registeredSections)
Joe Onorato99598ee2019-02-11 15:55:13 +0000522 :mWorkDirectory(workDirectory),
523 mWriter(batch),
Mike Ma643de922019-12-17 10:56:17 -0800524 mBatch(batch),
525 mRegisteredSections(registeredSections) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000526}
527
528Reporter::~Reporter() {
529}
530
531void Reporter::runReport(size_t* reportByteSize) {
Joe Onorato1754d742016-11-21 17:51:35 -0800532 status_t err = NO_ERROR;
Joe Onorato99598ee2019-02-11 15:55:13 +0000533
534 IncidentMetadata metadata;
535 int persistedPrivacyPolicy = PRIVACY_POLICY_UNSET;
Joe Onorato1754d742016-11-21 17:51:35 -0800536
Joe Onorato99598ee2019-02-11 15:55:13 +0000537 (*reportByteSize) = 0;
Joe Onorato1754d742016-11-21 17:51:35 -0800538
539 // Tell everyone that we're starting.
Joe Onorato99598ee2019-02-11 15:55:13 +0000540 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();
Joe Onorato1754d742016-11-21 17:51:35 -0800595 }
596 }
597
Joe Onorato99598ee2019-02-11 15:55:13 +0000598 // 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
Mike Mab6f7c472020-03-03 17:58:35 -0800612 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
Joe Onorato99598ee2019-02-11 15:55:13 +0000619 // 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.
Yao Chencbafce92019-04-01 15:56:44 -0700628 write_header_section(request->getFd(), buf->data(), buf->size());
Joe Onorato99598ee2019-02-11 15:55:13 +0000629 }
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();
Joe Onorato1754d742016-11-21 17:51:35 -0800635
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.
Yi Jinb592e3b2018-02-01 15:17:04 -0800638 for (const Section** section = SECTION_LIST; *section; section++) {
Mike Ma643de922019-12-17 10:56:17 -0800639 if (execute_section(*section, &metadata, reportByteSize) != NO_ERROR) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000640 goto DONE;
641 }
Mike Ma643de922019-12-17 10:56:17 -0800642 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000643
Mike Ma643de922019-12-17 10:56:17 -0800644 for (const Section* section : mRegisteredSections) {
645 if (execute_section(section, &metadata, reportByteSize) != NO_ERROR) {
646 goto DONE;
647 }
Joe Onorato1754d742016-11-21 17:51:35 -0800648 }
649
Yi Jinedfd5bb2017-09-06 17:09:11 -0700650DONE:
Joe Onorato99598ee2019-02-11 15:55:13 +0000651 // Finish up the persisted file.
652 if (mPersistedFile != nullptr) {
653 mPersistedFile->closeDataFile();
Yi Jin329130b2018-02-09 16:47:47 -0800654
Joe Onorato99598ee2019-02-11 15:55:13 +0000655 // Set the stored metadata
656 IncidentReportArgs combinedArgs;
657 mBatch->getCombinedPersistedArgs(&combinedArgs);
658 IncidentMetadata persistedMetadata;
659 make_metadata(&persistedMetadata, metadata, mPersistedFile->getTimestampNs(),
Joe Onorato7a406b42019-04-12 18:11:30 -0700660 persistedPrivacyPolicy, combinedArgs);
Joe Onorato99598ee2019-02-11 15:55:13 +0000661 mPersistedFile->setMetadata(persistedMetadata);
Joe Onorato1754d742016-11-21 17:51:35 -0800662
Joe Onorato99598ee2019-02-11 15:55:13 +0000663 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);
Joe Onorato1754d742016-11-21 17:51:35 -0800670 }
671 }
672
Joe Onorato99598ee2019-02-11 15:55:13 +0000673 // 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));
Joe Onorato1754d742016-11-21 17:51:35 -0800683 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000684 });
Joe Onorato1754d742016-11-21 17:51:35 -0800685
Joe Onorato99598ee2019-02-11 15:55:13 +0000686 // 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 });
Joe Onorato1754d742016-11-21 17:51:35 -0800700 }
Mike Ma892ccd92020-03-20 16:30:37 -0700701 clear_buffer_pool();
Joe Onorato99598ee2019-02-11 15:55:13 +0000702 ALOGI("Done taking incident report err=%s", strerror(-err));
Joe Onorato1754d742016-11-21 17:51:35 -0800703}
704
Mike Ma643de922019-12-17 10:56:17 -0800705status_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
Joe Onorato99598ee2019-02-11 15:55:13 +0000754void 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;
Joe Onorato1754d742016-11-21 17:51:35 -0800771 }
Joe Onorato1754d742016-11-21 17:51:35 -0800772 }
Joe Onorato1754d742016-11-21 17:51:35 -0800773
Joe Onorato99598ee2019-02-11 15:55:13 +0000774 // 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 }
Joe Onorato1754d742016-11-21 17:51:35 -0800787}
Yi Jin6cacbcb2018-03-30 14:04:52 -0700788
789} // namespace incidentd
790} // namespace os
791} // namespace android