Loading Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -409,6 +409,7 @@ filegroup { filegroup { name: "libincident_aidl", srcs: [ "core/java/android/os/IIncidentDumpCallback.aidl", "core/java/android/os/IIncidentManager.aidl", "core/java/android/os/IIncidentReportStatusListener.aidl", ], Loading cmds/incidentd/src/IncidentService.cpp +51 −4 Original line number Diff line number Diff line Loading @@ -123,14 +123,17 @@ static string build_uri(const string& pkg, const string& cls, const string& id) // ================================================================================ ReportHandler::ReportHandler(const sp<WorkDirectory>& workDirectory, const sp<Broadcaster>& broadcaster, const sp<Looper>& handlerLooper, const sp<Throttler>& throttler) const sp<Broadcaster>& broadcaster, const sp<Looper>& handlerLooper, const sp<Throttler>& throttler, const vector<BringYourOwnSection*>& registeredSections) :mLock(), mWorkDirectory(workDirectory), mBroadcaster(broadcaster), mHandlerLooper(handlerLooper), mBacklogDelay(DEFAULT_DELAY_NS), mThrottler(throttler), mRegisteredSections(registeredSections), mBatch(new ReportBatch()) { } Loading Loading @@ -185,7 +188,7 @@ void ReportHandler::take_report() { return; } sp<Reporter> reporter = new Reporter(mWorkDirectory, batch); sp<Reporter> reporter = new Reporter(mWorkDirectory, batch, mRegisteredSections); // Take the report, which might take a while. More requests might queue // up while we're doing this, and we'll handle them in their next batch. Loading Loading @@ -237,7 +240,7 @@ IncidentService::IncidentService(const sp<Looper>& handlerLooper) { mWorkDirectory = new WorkDirectory(); mBroadcaster = new Broadcaster(mWorkDirectory); mHandler = new ReportHandler(mWorkDirectory, mBroadcaster, handlerLooper, mThrottler); mThrottler, mRegisteredSections); mBroadcaster->setHandler(mHandler); } Loading Loading @@ -327,6 +330,11 @@ Status IncidentService::reportIncidentToDumpstate(unique_fd stream, incidentArgs.addSection(id); } } for (const Section* section : mRegisteredSections) { if (!section_requires_specific_mention(section->id)) { incidentArgs.addSection(section->id); } } // The ReportRequest takes ownership of the fd, so we need to dup it. int fd = dup(stream.get()); Loading @@ -339,6 +347,45 @@ Status IncidentService::reportIncidentToDumpstate(unique_fd stream, return Status::ok(); } Status IncidentService::registerSection(const int id, const String16& name16, const sp<IIncidentDumpCallback>& callback) { const char* name = String8(name16).c_str(); ALOGI("Register section %d: %s", id, name); if (callback == nullptr) { return Status::fromExceptionCode(Status::EX_NULL_POINTER); } const uid_t callingUid = IPCThreadState::self()->getCallingUid(); for (int i = 0; i < mRegisteredSections.size(); i++) { if (mRegisteredSections.at(i)->id == id) { if (mRegisteredSections.at(i)->uid != callingUid) { ALOGW("Error registering section %d: calling uid does not match", id); return Status::fromExceptionCode(Status::EX_SECURITY); } mRegisteredSections.at(i) = new BringYourOwnSection(id, name, callingUid, callback); return Status::ok(); } } mRegisteredSections.push_back(new BringYourOwnSection(id, name, callingUid, callback)); return Status::ok(); } Status IncidentService::unregisterSection(const int id) { ALOGI("Unregister section %d", id); uid_t callingUid = IPCThreadState::self()->getCallingUid(); for (auto it = mRegisteredSections.begin(); it != mRegisteredSections.end(); it++) { if ((*it)->id == id) { if ((*it)->uid != callingUid) { ALOGW("Error unregistering section %d: calling uid does not match", id); return Status::fromExceptionCode(Status::EX_SECURITY); } mRegisteredSections.erase(it); return Status::ok(); } } ALOGW("Section %d not found", id); return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE); } Status IncidentService::systemRunning() { if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, Loading cmds/incidentd/src/IncidentService.h +14 −2 Original line number Diff line number Diff line Loading @@ -40,12 +40,16 @@ using namespace android::base; using namespace android::binder; using namespace android::os; class BringYourOwnSection; // ================================================================================ class ReportHandler : public MessageHandler { public: ReportHandler(const sp<WorkDirectory>& workDirectory, const sp<Broadcaster>& broadcaster, const sp<Looper>& handlerLooper, const sp<Throttler>& throttler); const sp<Broadcaster>& broadcaster, const sp<Looper>& handlerLooper, const sp<Throttler>& throttler, const vector<BringYourOwnSection*>& registeredSections); virtual ~ReportHandler(); virtual void handleMessage(const Message& message); Loading Loading @@ -79,6 +83,8 @@ private: nsecs_t mBacklogDelay; sp<Throttler> mThrottler; const vector<BringYourOwnSection*>& mRegisteredSections; sp<ReportBatch> mBatch; /** Loading Loading @@ -126,6 +132,11 @@ public: virtual Status reportIncidentToDumpstate(unique_fd stream, const sp<IIncidentReportStatusListener>& listener); virtual Status registerSection(int id, const String16& name, const sp<IIncidentDumpCallback>& callback); virtual Status unregisterSection(int id); virtual Status systemRunning(); virtual Status getIncidentReportList(const String16& pkg, const String16& cls, Loading @@ -149,6 +160,7 @@ private: sp<Broadcaster> mBroadcaster; sp<ReportHandler> mHandler; sp<Throttler> mThrottler; vector<BringYourOwnSection*> mRegisteredSections; /** * Commands print out help. Loading cmds/incidentd/src/Reporter.cpp +59 −43 Original line number Diff line number Diff line Loading @@ -364,7 +364,6 @@ void ReportWriter::startSection(int sectionId) { mSectionBufferSuccess = false; mHadError = false; mSectionErrors.clear(); } void ReportWriter::setSectionStats(const FdBuffer& buffer) { Loading Loading @@ -470,10 +469,13 @@ status_t ReportWriter::writeSection(const FdBuffer& buffer) { // ================================================================================ Reporter::Reporter(const sp<WorkDirectory>& workDirectory, const sp<ReportBatch>& batch) Reporter::Reporter(const sp<WorkDirectory>& workDirectory, const sp<ReportBatch>& batch, const vector<BringYourOwnSection*>& registeredSections) :mWorkDirectory(workDirectory), mWriter(batch), mBatch(batch) { mBatch(batch), mRegisteredSections(registeredSections) { } Reporter::~Reporter() { Loading Loading @@ -580,50 +582,15 @@ void Reporter::runReport(size_t* reportByteSize) { // For each of the report fields, see if we need it, and if so, execute the command // and report to those that care that we're doing it. for (const Section** section = SECTION_LIST; *section; section++) { const int sectionId = (*section)->id; // If nobody wants this section, skip it. if (!mBatch->containsSection(sectionId)) { continue; if (execute_section(*section, &metadata, reportByteSize) != NO_ERROR) { goto DONE; } } ALOGD("Start incident report section %d '%s'", sectionId, (*section)->name.string()); IncidentMetadata::SectionStats* sectionMetadata = metadata.add_sections(); // Notify listener of starting mBatch->forEachListener(sectionId, [sectionId](const auto& listener) { listener->onReportSectionStatus( sectionId, IIncidentReportStatusListener::STATUS_STARTING); }); // Go get the data and write it into the file descriptors. mWriter.startSection(sectionId); err = (*section)->Execute(&mWriter); mWriter.endSection(sectionMetadata); // Sections returning errors are fatal. Most errors should not be fatal. if (err != NO_ERROR) { mWriter.error((*section), err, "Section failed. Stopping report."); for (const Section* section : mRegisteredSections) { if (execute_section(section, &metadata, reportByteSize) != NO_ERROR) { goto DONE; } // The returned max data size is used for throttling too many incident reports. (*reportByteSize) += sectionMetadata->report_size_bytes(); // For any requests that failed during this section, remove them now. We do this // before calling back about section finished, so listeners do not erroniously get the // impression that the section succeeded. But we do it here instead of inside // writeSection so that the callback is done from a known context and not from the // bowels of a section, where changing the batch could cause odd errors. cancel_and_remove_failed_requests(); // Notify listener of finishing mBatch->forEachListener(sectionId, [sectionId](const auto& listener) { listener->onReportSectionStatus( sectionId, IIncidentReportStatusListener::STATUS_FINISHED); }); ALOGD("Finish incident report section %d '%s'", sectionId, (*section)->name.string()); } DONE: Loading Loading @@ -681,6 +648,55 @@ DONE: ALOGI("Done taking incident report err=%s", strerror(-err)); } status_t Reporter::execute_section(const Section* section, IncidentMetadata* metadata, size_t* reportByteSize) { const int sectionId = section->id; // If nobody wants this section, skip it. if (!mBatch->containsSection(sectionId)) { return NO_ERROR; } ALOGD("Start incident report section %d '%s'", sectionId, section->name.string()); IncidentMetadata::SectionStats* sectionMetadata = metadata->add_sections(); // Notify listener of starting mBatch->forEachListener(sectionId, [sectionId](const auto& listener) { listener->onReportSectionStatus( sectionId, IIncidentReportStatusListener::STATUS_STARTING); }); // Go get the data and write it into the file descriptors. mWriter.startSection(sectionId); status_t err = section->Execute(&mWriter); mWriter.endSection(sectionMetadata); // Sections returning errors are fatal. Most errors should not be fatal. if (err != NO_ERROR) { mWriter.error(section, err, "Section failed. Stopping report."); return err; } // The returned max data size is used for throttling too many incident reports. (*reportByteSize) += sectionMetadata->report_size_bytes(); // For any requests that failed during this section, remove them now. We do this // before calling back about section finished, so listeners do not erroniously get the // impression that the section succeeded. But we do it here instead of inside // writeSection so that the callback is done from a known context and not from the // bowels of a section, where changing the batch could cause odd errors. cancel_and_remove_failed_requests(); // Notify listener of finishing mBatch->forEachListener(sectionId, [sectionId](const auto& listener) { listener->onReportSectionStatus( sectionId, IIncidentReportStatusListener::STATUS_FINISHED); }); ALOGD("Finish incident report section %d '%s'", sectionId, section->name.string()); return NO_ERROR; } void Reporter::cancel_and_remove_failed_requests() { // Handle a failure in the persisted file if (mPersistedFile != nullptr) { Loading cmds/incidentd/src/Reporter.h +10 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "frameworks/base/core/proto/android/os/metadata.pb.h" #include <android/content/ComponentName.h> #include <android/os/IIncidentReportStatusListener.h> #include <android/os/IIncidentDumpCallback.h> #include <android/os/IncidentReportArgs.h> #include <android/util/protobuf.h> Loading @@ -39,6 +40,7 @@ using namespace std; using namespace android::content; using namespace android::os; class BringYourOwnSection; class Section; // ================================================================================ Loading Loading @@ -122,7 +124,7 @@ public: void forEachStreamingRequest(const function<void (const sp<ReportRequest>&)>& func); /** * Call func(request) for each file descriptor that has * Call func(request) for each file descriptor. */ void forEachFd(int sectionId, const function<void (const sp<ReportRequest>&)>& func); Loading Loading @@ -251,7 +253,9 @@ private: // ================================================================================ class Reporter : public virtual RefBase { public: Reporter(const sp<WorkDirectory>& workDirectory, const sp<ReportBatch>& batch); Reporter(const sp<WorkDirectory>& workDirectory, const sp<ReportBatch>& batch, const vector<BringYourOwnSection*>& registeredSections); virtual ~Reporter(); Loading @@ -263,6 +267,10 @@ private: ReportWriter mWriter; sp<ReportBatch> mBatch; sp<ReportFile> mPersistedFile; const vector<BringYourOwnSection*>& mRegisteredSections; status_t execute_section(const Section* section, IncidentMetadata* metadata, size_t* reportByteSize); void cancel_and_remove_failed_requests(); }; Loading Loading
Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -409,6 +409,7 @@ filegroup { filegroup { name: "libincident_aidl", srcs: [ "core/java/android/os/IIncidentDumpCallback.aidl", "core/java/android/os/IIncidentManager.aidl", "core/java/android/os/IIncidentReportStatusListener.aidl", ], Loading
cmds/incidentd/src/IncidentService.cpp +51 −4 Original line number Diff line number Diff line Loading @@ -123,14 +123,17 @@ static string build_uri(const string& pkg, const string& cls, const string& id) // ================================================================================ ReportHandler::ReportHandler(const sp<WorkDirectory>& workDirectory, const sp<Broadcaster>& broadcaster, const sp<Looper>& handlerLooper, const sp<Throttler>& throttler) const sp<Broadcaster>& broadcaster, const sp<Looper>& handlerLooper, const sp<Throttler>& throttler, const vector<BringYourOwnSection*>& registeredSections) :mLock(), mWorkDirectory(workDirectory), mBroadcaster(broadcaster), mHandlerLooper(handlerLooper), mBacklogDelay(DEFAULT_DELAY_NS), mThrottler(throttler), mRegisteredSections(registeredSections), mBatch(new ReportBatch()) { } Loading Loading @@ -185,7 +188,7 @@ void ReportHandler::take_report() { return; } sp<Reporter> reporter = new Reporter(mWorkDirectory, batch); sp<Reporter> reporter = new Reporter(mWorkDirectory, batch, mRegisteredSections); // Take the report, which might take a while. More requests might queue // up while we're doing this, and we'll handle them in their next batch. Loading Loading @@ -237,7 +240,7 @@ IncidentService::IncidentService(const sp<Looper>& handlerLooper) { mWorkDirectory = new WorkDirectory(); mBroadcaster = new Broadcaster(mWorkDirectory); mHandler = new ReportHandler(mWorkDirectory, mBroadcaster, handlerLooper, mThrottler); mThrottler, mRegisteredSections); mBroadcaster->setHandler(mHandler); } Loading Loading @@ -327,6 +330,11 @@ Status IncidentService::reportIncidentToDumpstate(unique_fd stream, incidentArgs.addSection(id); } } for (const Section* section : mRegisteredSections) { if (!section_requires_specific_mention(section->id)) { incidentArgs.addSection(section->id); } } // The ReportRequest takes ownership of the fd, so we need to dup it. int fd = dup(stream.get()); Loading @@ -339,6 +347,45 @@ Status IncidentService::reportIncidentToDumpstate(unique_fd stream, return Status::ok(); } Status IncidentService::registerSection(const int id, const String16& name16, const sp<IIncidentDumpCallback>& callback) { const char* name = String8(name16).c_str(); ALOGI("Register section %d: %s", id, name); if (callback == nullptr) { return Status::fromExceptionCode(Status::EX_NULL_POINTER); } const uid_t callingUid = IPCThreadState::self()->getCallingUid(); for (int i = 0; i < mRegisteredSections.size(); i++) { if (mRegisteredSections.at(i)->id == id) { if (mRegisteredSections.at(i)->uid != callingUid) { ALOGW("Error registering section %d: calling uid does not match", id); return Status::fromExceptionCode(Status::EX_SECURITY); } mRegisteredSections.at(i) = new BringYourOwnSection(id, name, callingUid, callback); return Status::ok(); } } mRegisteredSections.push_back(new BringYourOwnSection(id, name, callingUid, callback)); return Status::ok(); } Status IncidentService::unregisterSection(const int id) { ALOGI("Unregister section %d", id); uid_t callingUid = IPCThreadState::self()->getCallingUid(); for (auto it = mRegisteredSections.begin(); it != mRegisteredSections.end(); it++) { if ((*it)->id == id) { if ((*it)->uid != callingUid) { ALOGW("Error unregistering section %d: calling uid does not match", id); return Status::fromExceptionCode(Status::EX_SECURITY); } mRegisteredSections.erase(it); return Status::ok(); } } ALOGW("Section %d not found", id); return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE); } Status IncidentService::systemRunning() { if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, Loading
cmds/incidentd/src/IncidentService.h +14 −2 Original line number Diff line number Diff line Loading @@ -40,12 +40,16 @@ using namespace android::base; using namespace android::binder; using namespace android::os; class BringYourOwnSection; // ================================================================================ class ReportHandler : public MessageHandler { public: ReportHandler(const sp<WorkDirectory>& workDirectory, const sp<Broadcaster>& broadcaster, const sp<Looper>& handlerLooper, const sp<Throttler>& throttler); const sp<Broadcaster>& broadcaster, const sp<Looper>& handlerLooper, const sp<Throttler>& throttler, const vector<BringYourOwnSection*>& registeredSections); virtual ~ReportHandler(); virtual void handleMessage(const Message& message); Loading Loading @@ -79,6 +83,8 @@ private: nsecs_t mBacklogDelay; sp<Throttler> mThrottler; const vector<BringYourOwnSection*>& mRegisteredSections; sp<ReportBatch> mBatch; /** Loading Loading @@ -126,6 +132,11 @@ public: virtual Status reportIncidentToDumpstate(unique_fd stream, const sp<IIncidentReportStatusListener>& listener); virtual Status registerSection(int id, const String16& name, const sp<IIncidentDumpCallback>& callback); virtual Status unregisterSection(int id); virtual Status systemRunning(); virtual Status getIncidentReportList(const String16& pkg, const String16& cls, Loading @@ -149,6 +160,7 @@ private: sp<Broadcaster> mBroadcaster; sp<ReportHandler> mHandler; sp<Throttler> mThrottler; vector<BringYourOwnSection*> mRegisteredSections; /** * Commands print out help. Loading
cmds/incidentd/src/Reporter.cpp +59 −43 Original line number Diff line number Diff line Loading @@ -364,7 +364,6 @@ void ReportWriter::startSection(int sectionId) { mSectionBufferSuccess = false; mHadError = false; mSectionErrors.clear(); } void ReportWriter::setSectionStats(const FdBuffer& buffer) { Loading Loading @@ -470,10 +469,13 @@ status_t ReportWriter::writeSection(const FdBuffer& buffer) { // ================================================================================ Reporter::Reporter(const sp<WorkDirectory>& workDirectory, const sp<ReportBatch>& batch) Reporter::Reporter(const sp<WorkDirectory>& workDirectory, const sp<ReportBatch>& batch, const vector<BringYourOwnSection*>& registeredSections) :mWorkDirectory(workDirectory), mWriter(batch), mBatch(batch) { mBatch(batch), mRegisteredSections(registeredSections) { } Reporter::~Reporter() { Loading Loading @@ -580,50 +582,15 @@ void Reporter::runReport(size_t* reportByteSize) { // For each of the report fields, see if we need it, and if so, execute the command // and report to those that care that we're doing it. for (const Section** section = SECTION_LIST; *section; section++) { const int sectionId = (*section)->id; // If nobody wants this section, skip it. if (!mBatch->containsSection(sectionId)) { continue; if (execute_section(*section, &metadata, reportByteSize) != NO_ERROR) { goto DONE; } } ALOGD("Start incident report section %d '%s'", sectionId, (*section)->name.string()); IncidentMetadata::SectionStats* sectionMetadata = metadata.add_sections(); // Notify listener of starting mBatch->forEachListener(sectionId, [sectionId](const auto& listener) { listener->onReportSectionStatus( sectionId, IIncidentReportStatusListener::STATUS_STARTING); }); // Go get the data and write it into the file descriptors. mWriter.startSection(sectionId); err = (*section)->Execute(&mWriter); mWriter.endSection(sectionMetadata); // Sections returning errors are fatal. Most errors should not be fatal. if (err != NO_ERROR) { mWriter.error((*section), err, "Section failed. Stopping report."); for (const Section* section : mRegisteredSections) { if (execute_section(section, &metadata, reportByteSize) != NO_ERROR) { goto DONE; } // The returned max data size is used for throttling too many incident reports. (*reportByteSize) += sectionMetadata->report_size_bytes(); // For any requests that failed during this section, remove them now. We do this // before calling back about section finished, so listeners do not erroniously get the // impression that the section succeeded. But we do it here instead of inside // writeSection so that the callback is done from a known context and not from the // bowels of a section, where changing the batch could cause odd errors. cancel_and_remove_failed_requests(); // Notify listener of finishing mBatch->forEachListener(sectionId, [sectionId](const auto& listener) { listener->onReportSectionStatus( sectionId, IIncidentReportStatusListener::STATUS_FINISHED); }); ALOGD("Finish incident report section %d '%s'", sectionId, (*section)->name.string()); } DONE: Loading Loading @@ -681,6 +648,55 @@ DONE: ALOGI("Done taking incident report err=%s", strerror(-err)); } status_t Reporter::execute_section(const Section* section, IncidentMetadata* metadata, size_t* reportByteSize) { const int sectionId = section->id; // If nobody wants this section, skip it. if (!mBatch->containsSection(sectionId)) { return NO_ERROR; } ALOGD("Start incident report section %d '%s'", sectionId, section->name.string()); IncidentMetadata::SectionStats* sectionMetadata = metadata->add_sections(); // Notify listener of starting mBatch->forEachListener(sectionId, [sectionId](const auto& listener) { listener->onReportSectionStatus( sectionId, IIncidentReportStatusListener::STATUS_STARTING); }); // Go get the data and write it into the file descriptors. mWriter.startSection(sectionId); status_t err = section->Execute(&mWriter); mWriter.endSection(sectionMetadata); // Sections returning errors are fatal. Most errors should not be fatal. if (err != NO_ERROR) { mWriter.error(section, err, "Section failed. Stopping report."); return err; } // The returned max data size is used for throttling too many incident reports. (*reportByteSize) += sectionMetadata->report_size_bytes(); // For any requests that failed during this section, remove them now. We do this // before calling back about section finished, so listeners do not erroniously get the // impression that the section succeeded. But we do it here instead of inside // writeSection so that the callback is done from a known context and not from the // bowels of a section, where changing the batch could cause odd errors. cancel_and_remove_failed_requests(); // Notify listener of finishing mBatch->forEachListener(sectionId, [sectionId](const auto& listener) { listener->onReportSectionStatus( sectionId, IIncidentReportStatusListener::STATUS_FINISHED); }); ALOGD("Finish incident report section %d '%s'", sectionId, section->name.string()); return NO_ERROR; } void Reporter::cancel_and_remove_failed_requests() { // Handle a failure in the persisted file if (mPersistedFile != nullptr) { Loading
cmds/incidentd/src/Reporter.h +10 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "frameworks/base/core/proto/android/os/metadata.pb.h" #include <android/content/ComponentName.h> #include <android/os/IIncidentReportStatusListener.h> #include <android/os/IIncidentDumpCallback.h> #include <android/os/IncidentReportArgs.h> #include <android/util/protobuf.h> Loading @@ -39,6 +40,7 @@ using namespace std; using namespace android::content; using namespace android::os; class BringYourOwnSection; class Section; // ================================================================================ Loading Loading @@ -122,7 +124,7 @@ public: void forEachStreamingRequest(const function<void (const sp<ReportRequest>&)>& func); /** * Call func(request) for each file descriptor that has * Call func(request) for each file descriptor. */ void forEachFd(int sectionId, const function<void (const sp<ReportRequest>&)>& func); Loading Loading @@ -251,7 +253,9 @@ private: // ================================================================================ class Reporter : public virtual RefBase { public: Reporter(const sp<WorkDirectory>& workDirectory, const sp<ReportBatch>& batch); Reporter(const sp<WorkDirectory>& workDirectory, const sp<ReportBatch>& batch, const vector<BringYourOwnSection*>& registeredSections); virtual ~Reporter(); Loading @@ -263,6 +267,10 @@ private: ReportWriter mWriter; sp<ReportBatch> mBatch; sp<ReportFile> mPersistedFile; const vector<BringYourOwnSection*>& mRegisteredSections; status_t execute_section(const Section* section, IncidentMetadata* metadata, size_t* reportByteSize); void cancel_and_remove_failed_requests(); }; Loading