1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #define DEBUG false 17 #include "Log.h" 18 19 #include "Reporter.h" 20 21 #include "incidentd_util.h" 22 #include "Privacy.h" 23 #include "PrivacyFilter.h" 24 #include "proto_util.h" 25 #include "report_directory.h" 26 #include "section_list.h" 27 28 #include <android-base/file.h> 29 #include <android/os/DropBoxManager.h> 30 #include <android/util/protobuf.h> 31 #include <android/util/ProtoOutputStream.h> 32 #include <private/android_filesystem_config.h> 33 #include <utils/SystemClock.h> 34 35 #include <dirent.h> 36 #include <errno.h> 37 #include <fcntl.h> 38 #include <sys/stat.h> 39 #include <sys/types.h> 40 #include <string> 41 #include <time.h> 42 43 namespace android { 44 namespace os { 45 namespace incidentd { 46 47 using namespace android::util; 48 49 /** 50 * The field id of the metadata section from 51 * frameworks/base/core/proto/android/os/incident.proto 52 */ 53 const int FIELD_ID_METADATA = 2; 54 55 IncidentMetadata_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 69 70 static bool contains_section(const IncidentReportArgs& args, int sectionId) { 71 return args.containsSection(sectionId, section_requires_specific_mention(sectionId)); 72 } 73 74 static bool contains_section(const sp<ReportRequest>& args, int sectionId) { 75 return args->containsSection(sectionId); 76 } 77 78 // ARGS must have a containsSection(int) method 79 template <typename ARGS> 80 void make_metadata(IncidentMetadata* result, const IncidentMetadata& full, 81 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); 88 if (contains_section(args, sectionStats.id())) { 89 *result->add_sections() = sectionStats; 90 } 91 } 92 } 93 94 // ================================================================================ 95 class StreamingFilterFd : public FilterFd { 96 public: 97 StreamingFilterFd(uint8_t privacyPolicy, int fd, const sp<ReportRequest>& request); 98 99 virtual void onWriteError(status_t err); 100 101 private: 102 sp<ReportRequest> mRequest; 103 }; 104 105 StreamingFilterFd::StreamingFilterFd(uint8_t privacyPolicy, int fd, 106 const sp<ReportRequest>& request) 107 :FilterFd(privacyPolicy, fd), 108 mRequest(request) { 109 } 110 111 void StreamingFilterFd::onWriteError(status_t err) { 112 mRequest->setStatus(err); 113 } 114 115 116 // ================================================================================ 117 class PersistedFilterFd : public FilterFd { 118 public: 119 PersistedFilterFd(uint8_t privacyPolicy, int fd, const sp<ReportFile>& reportFile); 120 121 virtual void onWriteError(status_t err); 122 123 private: 124 sp<ReportFile> mReportFile; 125 }; 126 127 PersistedFilterFd::PersistedFilterFd(uint8_t privacyPolicy, int fd, 128 const sp<ReportFile>& reportFile) 129 :FilterFd(privacyPolicy, fd), 130 mReportFile(reportFile) { 131 } 132 133 void PersistedFilterFd::onWriteError(status_t err) { 134 mReportFile->setWriteError(err); 135 } 136 137 138 // ================================================================================ 139 ReportRequest::ReportRequest(const IncidentReportArgs& a, 140 const sp<IIncidentReportStatusListener>& listener, int fd) 141 :args(a), 142 mListener(listener), 143 mFd(fd), 144 mIsStreaming(fd >= 0), 145 mStatus(NO_ERROR) { 146 } 147 148 ReportRequest::~ReportRequest() { 149 if (mIsStreaming && mFd >= 0) { 150 // clean up the opened file descriptor 151 close(mFd); 152 } 153 } 154 155 bool ReportRequest::ok() { 156 return mFd >= 0 && mStatus == NO_ERROR; 157 } 158 159 bool ReportRequest::containsSection(int sectionId) const { 160 return args.containsSection(sectionId, section_requires_specific_mention(sectionId)); 161 } 162 163 void ReportRequest::closeFd() { 164 if (mIsStreaming && mFd >= 0) { 165 close(mFd); 166 mFd = -1; 167 } 168 } 169 170 // ================================================================================ 171 ReportBatch::ReportBatch() {} 172 173 ReportBatch::~ReportBatch() {} 174 175 void 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 } 186 } 187 188 void ReportBatch::addStreamingReport(const IncidentReportArgs& args, 189 const sp<IIncidentReportStatusListener>& listener, int streamFd) { 190 mStreamingRequests.push_back(new ReportRequest(args, listener, streamFd)); 191 } 192 193 bool ReportBatch::empty() const { 194 return mPersistedRequests.size() == 0 && mStreamingRequests.size() == 0; 195 } 196 197 sp<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 206 void 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 213 void 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 220 void 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 238 void 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 260 void 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 267 bool 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 285 void ReportBatch::clearPersistedRequests() { 286 mPersistedRequests.clear(); 287 } 288 289 void 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 297 void 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 305 void 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 320 void 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 // ================================================================================ 338 ReportWriter::ReportWriter(const sp<ReportBatch>& batch) 339 :mBatch(batch), 340 mPersistedFile(), 341 mMaxPersistedPrivacyPolicy(PRIVACY_POLICY_UNSET) { 342 } 343 344 ReportWriter::~ReportWriter() { 345 } 346 347 void ReportWriter::setPersistedFile(sp<ReportFile> file) { 348 mPersistedFile = file; 349 } 350 351 void ReportWriter::setMaxPersistedPrivacyPolicy(uint8_t privacyPolicy) { 352 mMaxPersistedPrivacyPolicy = privacyPolicy; 353 } 354 355 void 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 370 void 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 379 void 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 397 void 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 404 void 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 411 void 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. 449 status_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) { 460 if (request->ok() 461 && request->args.containsSection(mCurrentSectionId, 462 section_requires_specific_mention(mCurrentSectionId))) { 463 filter.addFd(new StreamingFilterFd(request->args.getPrivacyPolicy(), 464 request->getFd(), request)); 465 } 466 }); 467 468 return filter.writeData(buffer, PRIVACY_POLICY_LOCAL, &mMaxSectionDataFilteredSize); 469 } 470 471 472 // ================================================================================ 473 Reporter::Reporter(const sp<WorkDirectory>& workDirectory, const sp<ReportBatch>& batch) 474 :mWorkDirectory(workDirectory), 475 mWriter(batch), 476 mBatch(batch) { 477 } 478 479 Reporter::~Reporter() { 480 } 481 482 void Reporter::runReport(size_t* reportByteSize) { 483 status_t err = NO_ERROR; 484 485 IncidentMetadata metadata; 486 int persistedPrivacyPolicy = PRIVACY_POLICY_UNSET; 487 488 (*reportByteSize) = 0; 489 490 // Tell everyone that we're starting. 491 ALOGI("Starting incident report"); 492 mBatch->forEachListener([](const auto& listener) { listener->onReportStarted(); }); 493 494 if (mBatch->hasPersistedReports()) { 495 // Open a work file to contain the contents of all of the persisted reports. 496 // For this block, if we can't initialize the report file for some reason, 497 // then we will remove the persisted ReportRequests from the report, but 498 // continue with the streaming ones. 499 mPersistedFile = mWorkDirectory->createReportFile(); 500 ALOGI("Report will be persisted: envelope: %s data: %s", 501 mPersistedFile->getEnvelopeFileName().c_str(), 502 mPersistedFile->getDataFileName().c_str()); 503 504 // Record all of the metadata to the persisted file's metadata file. 505 // It will be read from there and reconstructed as the actual reports 506 // are sent out. 507 if (mPersistedFile != nullptr) { 508 mBatch->forEachPersistedRequest([this, &persistedPrivacyPolicy]( 509 const sp<ReportRequest>& request) { 510 mPersistedFile->addReport(request->args); 511 if (request->args.getPrivacyPolicy() < persistedPrivacyPolicy) { 512 persistedPrivacyPolicy = request->args.getPrivacyPolicy(); 513 } 514 }); 515 mPersistedFile->setMaxPersistedPrivacyPolicy(persistedPrivacyPolicy); 516 err = mPersistedFile->saveEnvelope(); 517 if (err != NO_ERROR) { 518 mWorkDirectory->remove(mPersistedFile); 519 mPersistedFile = nullptr; 520 } 521 mWriter.setMaxPersistedPrivacyPolicy(persistedPrivacyPolicy); 522 } 523 524 if (mPersistedFile != nullptr) { 525 err = mPersistedFile->startWritingDataFile(); 526 if (err != NO_ERROR) { 527 mWorkDirectory->remove(mPersistedFile); 528 mPersistedFile = nullptr; 529 } 530 } 531 532 if (mPersistedFile != nullptr) { 533 mWriter.setPersistedFile(mPersistedFile); 534 } else { 535 ALOGW("Error creating the persisted file, so clearing persisted reports."); 536 // If we couldn't open the file (permissions err, etc), then 537 // we still want to proceed with any streaming reports, but 538 // cancel all of the persisted ones. 539 mBatch->forEachPersistedRequest([](const sp<ReportRequest>& request) { 540 sp<IIncidentReportStatusListener> listener = request->getListener(); 541 if (listener != nullptr) { 542 listener->onReportFailed(); 543 } 544 }); 545 mBatch->clearPersistedRequests(); 546 } 547 } 548 549 // If we have a persisted ID, then we allow all the readers to see that. There's 550 // enough in the data to allow for a join, and nothing in here that intrisincally 551 // could ever prevent that, so just give them the ID. If we don't have that then we 552 // make and ID that's extremely likely to be unique, but clock resetting could allow 553 // it to be duplicate. 554 int64_t reportId; 555 if (mPersistedFile != nullptr) { 556 reportId = mPersistedFile->getTimestampNs(); 557 } else { 558 struct timespec spec; 559 clock_gettime(CLOCK_REALTIME, &spec); 560 reportId = (spec.tv_sec) * 1000 + spec.tv_nsec; 561 } 562 563 // Write the incident report headers - each request gets its own headers. It's different 564 // from the other top-level fields in IncidentReport that are the sections where the rest 565 // is all shared data (although with their own individual privacy filtering). 566 mBatch->forEachStreamingRequest([](const sp<ReportRequest>& request) { 567 const vector<vector<uint8_t>>& headers = request->args.headers(); 568 for (vector<vector<uint8_t>>::const_iterator buf = headers.begin(); buf != headers.end(); 569 buf++) { 570 // If there was an error now, there will be an error later and we will remove 571 // it from the list then. 572 write_header_section(request->getFd(), buf->data(), buf->size()); 573 } 574 }); 575 576 // If writing to any of the headers failed, we don't want to keep processing 577 // sections for it. 578 cancel_and_remove_failed_requests(); 579 580 // For each of the report fields, see if we need it, and if so, execute the command 581 // and report to those that care that we're doing it. 582 for (const Section** section = SECTION_LIST; *section; section++) { 583 const int sectionId = (*section)->id; 584 585 // If nobody wants this section, skip it. 586 if (!mBatch->containsSection(sectionId)) { 587 continue; 588 } 589 590 ALOGD("Start incident report section %d '%s'", sectionId, (*section)->name.string()); 591 IncidentMetadata::SectionStats* sectionMetadata = metadata.add_sections(); 592 593 // Notify listener of starting 594 mBatch->forEachListener(sectionId, [sectionId](const auto& listener) { 595 listener->onReportSectionStatus( 596 sectionId, IIncidentReportStatusListener::STATUS_STARTING); 597 }); 598 599 // Go get the data and write it into the file descriptors. 600 mWriter.startSection(sectionId); 601 err = (*section)->Execute(&mWriter); 602 mWriter.endSection(sectionMetadata); 603 604 // Sections returning errors are fatal. Most errors should not be fatal. 605 if (err != NO_ERROR) { 606 mWriter.error((*section), err, "Section failed. Stopping report."); 607 goto DONE; 608 } 609 610 // The returned max data size is used for throttling too many incident reports. 611 (*reportByteSize) += sectionMetadata->report_size_bytes(); 612 613 // For any requests that failed during this section, remove them now. We do this 614 // before calling back about section finished, so listeners do not erroniously get the 615 // impression that the section succeeded. But we do it here instead of inside 616 // writeSection so that the callback is done from a known context and not from the 617 // bowels of a section, where changing the batch could cause odd errors. 618 cancel_and_remove_failed_requests(); 619 620 // Notify listener of finishing 621 mBatch->forEachListener(sectionId, [sectionId](const auto& listener) { 622 listener->onReportSectionStatus( 623 sectionId, IIncidentReportStatusListener::STATUS_FINISHED); 624 }); 625 626 ALOGD("Finish incident report section %d '%s'", sectionId, (*section)->name.string()); 627 } 628 629 DONE: 630 // Finish up the persisted file. 631 if (mPersistedFile != nullptr) { 632 mPersistedFile->closeDataFile(); 633 634 // Set the stored metadata 635 IncidentReportArgs combinedArgs; 636 mBatch->getCombinedPersistedArgs(&combinedArgs); 637 IncidentMetadata persistedMetadata; 638 make_metadata(&persistedMetadata, metadata, mPersistedFile->getTimestampNs(), 639 persistedPrivacyPolicy, combinedArgs); 640 mPersistedFile->setMetadata(persistedMetadata); 641 642 mPersistedFile->markCompleted(); 643 err = mPersistedFile->saveEnvelope(); 644 if (err != NO_ERROR) { 645 ALOGW("mPersistedFile->saveEnvelope returned %s. Won't send broadcast", 646 strerror(-err)); 647 // Abandon ship. 648 mWorkDirectory->remove(mPersistedFile); 649 } 650 } 651 652 // Write the metadata to the streaming ones 653 mBatch->forEachStreamingRequest([reportId, &metadata](const sp<ReportRequest>& request) { 654 IncidentMetadata streamingMetadata; 655 make_metadata(&streamingMetadata, metadata, reportId, 656 request->args.getPrivacyPolicy(), request); 657 status_t nonFatalErr = write_section(request->getFd(), FIELD_ID_METADATA, 658 streamingMetadata); 659 if (nonFatalErr != NO_ERROR) { 660 ALOGW("Error writing the metadata to streaming incident report. This is the last" 661 " thing so we won't return an error: %s", strerror(nonFatalErr)); 662 } 663 }); 664 665 // Finish up the streaming ones. 666 mBatch->forEachStreamingRequest([](const sp<ReportRequest>& request) { 667 request->closeFd(); 668 }); 669 670 // Tell the listeners that we're done. 671 if (err == NO_ERROR) { 672 mBatch->forEachListener([](const auto& listener) { 673 listener->onReportFinished(); 674 }); 675 } else { 676 mBatch->forEachListener([](const auto& listener) { 677 listener->onReportFailed(); 678 }); 679 } 680 681 ALOGI("Done taking incident report err=%s", strerror(-err)); 682 } 683 684 void Reporter::cancel_and_remove_failed_requests() { 685 // Handle a failure in the persisted file 686 if (mPersistedFile != nullptr) { 687 if (mPersistedFile->getWriteError() != NO_ERROR) { 688 ALOGW("Error writing to the persisted file (%s). Closing it and canceling.", 689 strerror(-mPersistedFile->getWriteError())); 690 mBatch->forEachPersistedRequest([this](const sp<ReportRequest>& request) { 691 sp<IIncidentReportStatusListener> listener = request->getListener(); 692 if (listener != nullptr) { 693 listener->onReportFailed(); 694 } 695 mBatch->removeRequest(request); 696 }); 697 mWriter.setPersistedFile(nullptr); 698 mPersistedFile->closeDataFile(); 699 mWorkDirectory->remove(mPersistedFile); 700 mPersistedFile = nullptr; 701 } 702 } 703 704 // Handle failures in the streaming files 705 vector<sp<ReportRequest>> failed; 706 mBatch->getFailedRequests(&failed); 707 for (sp<ReportRequest>& request: failed) { 708 ALOGW("Error writing to a request stream (%s). Closing it and canceling.", 709 strerror(-request->getStatus())); 710 sp<IIncidentReportStatusListener> listener = request->getListener(); 711 if (listener != nullptr) { 712 listener->onReportFailed(); 713 } 714 request->closeFd(); // Will only close the streaming ones. 715 mBatch->removeRequest(request); 716 } 717 } 718 719 } // namespace incidentd 720 } // namespace os 721 } // namespace android 722