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 #pragma once 17 18 #include "incidentd_util.h" 19 #include "FdBuffer.h" 20 #include "WorkDirectory.h" 21 22 #include "frameworks/base/core/proto/android/os/metadata.pb.h" 23 #include <android/content/ComponentName.h> 24 #include <android/os/IIncidentReportStatusListener.h> 25 #include <android/os/IIncidentDumpCallback.h> 26 #include <android/os/IncidentReportArgs.h> 27 #include <android/util/protobuf.h> 28 29 #include <map> 30 #include <string> 31 #include <vector> 32 33 #include <time.h> 34 #include <stdarg.h> 35 36 namespace android { 37 namespace os { 38 namespace incidentd { 39 40 using namespace std; 41 using namespace android::content; 42 using namespace android::os; 43 44 class BringYourOwnSection; 45 class Section; 46 47 // ================================================================================ 48 class ReportRequest : public virtual RefBase { 49 public: 50 IncidentReportArgs args; 51 52 ReportRequest(const IncidentReportArgs& args, const sp<IIncidentReportStatusListener>& listener, 53 int fd); 54 virtual ~ReportRequest(); 55 isStreaming()56 bool isStreaming() { return mIsStreaming; } 57 setStatus(status_t err)58 void setStatus(status_t err) { mStatus = err; } getStatus()59 status_t getStatus() const { return mStatus; } 60 61 bool ok(); // returns true if the request is ok for write. 62 63 bool containsSection(int sectionId) const; 64 getListener()65 sp<IIncidentReportStatusListener> getListener() { return mListener; } 66 67 int getFd(); 68 69 int setPersistedFd(int fd); 70 71 status_t initGzipIfNecessary(); 72 73 void closeFd(); 74 75 private: 76 sp<IIncidentReportStatusListener> mListener; 77 int mFd; 78 bool mIsStreaming; 79 status_t mStatus; 80 pid_t mZipPid; 81 Fpipe mZipPipe; 82 }; 83 84 // ================================================================================ 85 class ReportBatch : public virtual RefBase { 86 public: 87 ReportBatch(); 88 virtual ~ReportBatch(); 89 90 // TODO: Should there be some kind of listener associated with the 91 // component? Could be good for getting status updates e.g. in the ui, 92 // as it progresses. But that's out of scope for now. 93 94 /** 95 * Schedule a report for the "main" report, where it will be delivered to 96 * the uploaders and/or dropbox. 97 */ 98 void addPersistedReport(const IncidentReportArgs& args); 99 100 /** 101 * Adds a ReportRequest to the queue for one that has a listener an and fd 102 */ 103 void addStreamingReport(const IncidentReportArgs& args, 104 const sp<IIncidentReportStatusListener>& listener, int streamFd); 105 106 /** 107 * Returns whether both queues are empty. 108 */ 109 bool empty() const; 110 111 /** 112 * Returns whether there are any persisted records. 113 */ hasPersistedReports()114 bool hasPersistedReports() const { return mPersistedRequests.size() > 0; } 115 116 /** 117 * Return the persisted request for the given component, or nullptr. 118 */ 119 sp<ReportRequest> getPersistedRequest(const ComponentName& component); 120 121 /** 122 * Call func(request) for each Request. 123 */ 124 void forEachPersistedRequest(const function<void (const sp<ReportRequest>&)>& func); 125 126 /** 127 * Call func(request) for each Request. 128 */ 129 void forEachStreamingRequest(const function<void (const sp<ReportRequest>&)>& func); 130 131 /** 132 * Call func(request) for each file descriptor. 133 */ 134 void forEachFd(int sectionId, const function<void (const sp<ReportRequest>&)>& func); 135 136 /** 137 * Call func(listener) for every listener in this batch. 138 */ 139 void forEachListener(const function<void (const sp<IIncidentReportStatusListener>&)>& func); 140 141 /** 142 * Call func(listener) for every listener in this batch that requests 143 * sectionId. 144 */ 145 void forEachListener(int sectionId, 146 const function<void (const sp<IIncidentReportStatusListener>&)>& func); 147 /** 148 * Get an IncidentReportArgs that represents the combined args for the 149 * persisted requests. 150 */ 151 void getCombinedPersistedArgs(IncidentReportArgs* results); 152 153 /** 154 * Return whether any of the requests contain the section. 155 */ 156 bool containsSection(int id); 157 158 /** 159 * Remove all of the broadcast (persisted) requests. 160 */ 161 void clearPersistedRequests(); 162 163 /** 164 * Move the streaming requests in this batch to that batch. After this call there 165 * will be no streaming requests in this batch. 166 */ 167 void transferStreamingRequests(const sp<ReportBatch>& that); 168 169 /** 170 * Move the persisted requests in this batch to that batch. After this call there 171 * will be no streaming requests in this batch. 172 */ 173 void transferPersistedRequests(const sp<ReportBatch>& that); 174 175 /** 176 * Get the requests that have encountered errors. 177 */ 178 void getFailedRequests(vector<sp<ReportRequest>>* requests); 179 180 /** 181 * Remove the request from whichever list it's in. 182 */ 183 void removeRequest(const sp<ReportRequest>& request); 184 185 186 private: 187 map<ComponentName, sp<ReportRequest>> mPersistedRequests; 188 vector<sp<ReportRequest>> mStreamingRequests; 189 }; 190 191 // ================================================================================ 192 class ReportWriter { 193 public: 194 ReportWriter(const sp<ReportBatch>& batch); 195 ~ReportWriter(); 196 197 void setPersistedFile(sp<ReportFile> file); 198 void setMaxPersistedPrivacyPolicy(uint8_t privacyPolicy); 199 200 void startSection(int sectionId); 201 void endSection(IncidentMetadata::SectionStats* sectionStats); 202 203 void setSectionStats(const FdBuffer& buffer); 204 205 void warning(const Section* section, status_t err, const char* format, ...); 206 void error(const Section* section, status_t err, const char* format, ...); 207 208 status_t writeSection(const FdBuffer& buffer); 209 210 private: 211 // Data about all requests 212 sp<ReportBatch> mBatch; 213 214 /** 215 * The file on disk where we will store the persisted file. 216 */ 217 sp<ReportFile> mPersistedFile; 218 219 /** 220 * The least restricted privacy policy of all of the perstited 221 * requests. We pre-filter to that to save disk space. 222 */ 223 uint8_t mMaxPersistedPrivacyPolicy; 224 225 /** 226 * The current section that is being written. 227 */ 228 int mCurrentSectionId; 229 230 /** 231 * The time that that the current section was started. 232 */ 233 int64_t mSectionStartTimeMs; 234 235 /** 236 * The last section that setSectionStats was called for, so if someone misses 237 * it we can log that. 238 */ 239 int mSectionStatsCalledForSectionId; 240 241 /* 242 * Fields for IncidentMetadata.SectionStats. Set by setSectionStats. Accessed by 243 * getSectionStats. 244 */ 245 int32_t mDumpSizeBytes; 246 int64_t mDumpDurationMs; 247 bool mSectionTimedOut; 248 bool mSectionTruncated; 249 bool mSectionBufferSuccess; 250 bool mHadError; 251 string mSectionErrors; 252 size_t mMaxSectionDataFilteredSize; 253 254 void vflog(const Section* section, status_t err, int level, const char* levelText, 255 const char* format, va_list args); 256 }; 257 258 // ================================================================================ 259 class Reporter : public virtual RefBase { 260 public: 261 Reporter(const sp<WorkDirectory>& workDirectory, 262 const sp<ReportBatch>& batch, 263 const vector<BringYourOwnSection*>& registeredSections); 264 265 virtual ~Reporter(); 266 267 // Run the report as described in the batch and args parameters. 268 void runReport(size_t* reportByteSize); 269 270 private: 271 sp<WorkDirectory> mWorkDirectory; 272 ReportWriter mWriter; 273 sp<ReportBatch> mBatch; 274 sp<ReportFile> mPersistedFile; 275 const vector<BringYourOwnSection*>& mRegisteredSections; 276 277 status_t execute_section(const Section* section, IncidentMetadata* metadata, 278 size_t* reportByteSize); 279 280 void cancel_and_remove_failed_requests(); 281 }; 282 283 } // namespace incidentd 284 } // namespace os 285 } // namespace android 286