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