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 17 #define LOG_TAG "incidentd" 18 19 #include "IncidentService.h" 20 21 #include "Reporter.h" 22 23 #include <binder/IPCThreadState.h> 24 #include <binder/IServiceManager.h> 25 #include <cutils/log.h> 26 #include <private/android_filesystem_config.h> 27 #include <utils/Looper.h> 28 29 #include <unistd.h> 30 31 using namespace android; 32 33 enum { 34 WHAT_RUN_REPORT = 1, 35 WHAT_SEND_BACKLOG_TO_DROPBOX = 2 36 }; 37 38 //#define DEFAULT_BACKLOG_DELAY_NS (1000000000LL * 60 * 5) 39 #define DEFAULT_BACKLOG_DELAY_NS (1000000000LL) 40 41 // ================================================================================ 42 String16 const DUMP_PERMISSION("android.permission.DUMP"); 43 String16 const USAGE_STATS_PERMISSION("android.permission.PACKAGE_USAGE_STATS"); 44 45 static Status 46 checkIncidentPermissions() 47 { 48 if (!checkCallingPermission(DUMP_PERMISSION)) { 49 ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP", 50 IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid()); 51 return Status::fromExceptionCode(Status::EX_SECURITY, 52 "Calling process does not have permission: android.permission.DUMP"); 53 } 54 if (!checkCallingPermission(USAGE_STATS_PERMISSION)) { 55 ALOGW("Calling pid %d and uid %d does not have permission: android.permission.USAGE_STATS", 56 IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid()); 57 return Status::fromExceptionCode(Status::EX_SECURITY, 58 "Calling process does not have permission: android.permission.USAGE_STATS"); 59 } 60 return Status::ok(); 61 } 62 63 64 // ================================================================================ 65 ReportRequestQueue::ReportRequestQueue() 66 { 67 } 68 69 ReportRequestQueue::~ReportRequestQueue() 70 { 71 } 72 73 void 74 ReportRequestQueue::addRequest(const sp<ReportRequest>& request) 75 { 76 unique_lock<mutex> lock(mLock); 77 mQueue.push_back(request); 78 } 79 80 sp<ReportRequest> 81 ReportRequestQueue::getNextRequest() 82 { 83 unique_lock<mutex> lock(mLock); 84 if (mQueue.empty()) { 85 return NULL; 86 } else { 87 sp<ReportRequest> front(mQueue.front()); 88 mQueue.pop_front(); 89 return front; 90 } 91 } 92 93 94 // ================================================================================ 95 ReportHandler::ReportHandler(const sp<Looper>& handlerLooper, const sp<ReportRequestQueue>& queue) 96 :mBacklogDelay(DEFAULT_BACKLOG_DELAY_NS), 97 mHandlerLooper(handlerLooper), 98 mQueue(queue) 99 { 100 } 101 102 ReportHandler::~ReportHandler() 103 { 104 } 105 106 void 107 ReportHandler::handleMessage(const Message& message) 108 { 109 switch (message.what) { 110 case WHAT_RUN_REPORT: 111 run_report(); 112 break; 113 case WHAT_SEND_BACKLOG_TO_DROPBOX: 114 send_backlog_to_dropbox(); 115 break; 116 } 117 } 118 119 void 120 ReportHandler::scheduleRunReport(const sp<ReportRequest>& request) 121 { 122 mQueue->addRequest(request); 123 mHandlerLooper->removeMessages(this, WHAT_RUN_REPORT); 124 mHandlerLooper->sendMessage(this, Message(WHAT_RUN_REPORT)); 125 } 126 127 void 128 ReportHandler::scheduleSendBacklogToDropbox() 129 { 130 unique_lock<mutex> lock(mLock); 131 mBacklogDelay = DEFAULT_BACKLOG_DELAY_NS; 132 schedule_send_backlog_to_dropbox_locked(); 133 } 134 135 void 136 ReportHandler::schedule_send_backlog_to_dropbox_locked() 137 { 138 mHandlerLooper->removeMessages(this, WHAT_SEND_BACKLOG_TO_DROPBOX); 139 mHandlerLooper->sendMessageDelayed(mBacklogDelay, this, 140 Message(WHAT_SEND_BACKLOG_TO_DROPBOX)); 141 } 142 143 void 144 ReportHandler::run_report() 145 { 146 sp<Reporter> reporter = new Reporter(); 147 148 // Merge all of the requests into one that has all of the 149 // requested fields. 150 while (true) { 151 sp<ReportRequest> request = mQueue->getNextRequest(); 152 if (request == NULL) { 153 break; 154 } 155 reporter->batch.add(request); 156 reporter->args.merge(request->args); 157 } 158 159 // Take the report, which might take a while. More requests might queue 160 // up while we're doing this, and we'll handle them in their next batch. 161 // TODO: We should further rate-limit the reports to no more than N per time-period. 162 Reporter::run_report_status_t reportStatus = reporter->runReport(); 163 if (reportStatus == Reporter::REPORT_NEEDS_DROPBOX) { 164 unique_lock<mutex> lock(mLock); 165 schedule_send_backlog_to_dropbox_locked(); 166 } 167 } 168 169 void 170 ReportHandler::send_backlog_to_dropbox() 171 { 172 if (Reporter::upload_backlog() == Reporter::REPORT_NEEDS_DROPBOX) { 173 // There was a failure. Exponential backoff. 174 unique_lock<mutex> lock(mLock); 175 mBacklogDelay *= 2; 176 ALOGI("Error sending to dropbox. Trying again in %lld minutes", 177 (mBacklogDelay / (1000000000LL * 60))); 178 schedule_send_backlog_to_dropbox_locked(); 179 } else { 180 mBacklogDelay = DEFAULT_BACKLOG_DELAY_NS; 181 } 182 } 183 184 // ================================================================================ 185 IncidentService::IncidentService(const sp<Looper>& handlerLooper) 186 :mQueue(new ReportRequestQueue()) 187 { 188 mHandler = new ReportHandler(handlerLooper, mQueue); 189 } 190 191 IncidentService::~IncidentService() 192 { 193 } 194 195 Status 196 IncidentService::reportIncident(const IncidentReportArgs& args) 197 { 198 ALOGI("reportIncident"); 199 200 Status status = checkIncidentPermissions(); 201 if (!status.isOk()) { 202 return status; 203 } 204 205 mHandler->scheduleRunReport(new ReportRequest(args, NULL, -1)); 206 207 return Status::ok(); 208 } 209 210 Status 211 IncidentService::reportIncidentToStream(const IncidentReportArgs& args, 212 const sp<IIncidentReportStatusListener>& listener, const unique_fd& stream) 213 { 214 ALOGI("reportIncidentToStream"); 215 216 Status status = checkIncidentPermissions(); 217 if (!status.isOk()) { 218 return status; 219 } 220 221 int fd = dup(stream.get()); 222 if (fd < 0) { 223 return Status::fromStatusT(-errno); 224 } 225 226 mHandler->scheduleRunReport(new ReportRequest(args, listener, fd)); 227 228 return Status::ok(); 229 } 230 231 Status 232 IncidentService::systemRunning() 233 { 234 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { 235 return Status::fromExceptionCode(Status::EX_SECURITY, 236 "Only system uid can call systemRunning"); 237 } 238 239 // When system_server is up and running, schedule the dropbox task to run. 240 mHandler->scheduleSendBacklogToDropbox(); 241 242 return Status::ok(); 243 } 244 245