blob: 654036ec6ab7c7fc04e80d30e199d8df19f3e676 [file] [log] [blame]
Joe Onorato1754d742016-11-21 17:51:35 -08001/*
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
31using namespace android;
32
33enum {
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// ================================================================================
42String16 const DUMP_PERMISSION("android.permission.DUMP");
43String16 const USAGE_STATS_PERMISSION("android.permission.PACKAGE_USAGE_STATS");
44
45static Status
Yi Jin4bab3a12018-01-10 16:50:59 -080046checkIncidentPermissions(const IncidentReportArgs& args)
Joe Onorato1754d742016-11-21 17:51:35 -080047{
Yi Jin437aa6e2018-01-10 11:34:26 -080048 uid_t callingUid = IPCThreadState::self()->getCallingUid();
Yi Jinafb36062018-01-31 19:14:25 -080049 pid_t callingPid = IPCThreadState::self()->getCallingPid();
Yi Jin437aa6e2018-01-10 11:34:26 -080050 if (callingUid == AID_ROOT || callingUid == AID_SHELL) {
51 // root doesn't have permission.DUMP if don't do this!
52 return Status::ok();
53 }
54
Yi Jin4bab3a12018-01-10 16:50:59 -080055 // checking calling permission.
Joe Onorato1754d742016-11-21 17:51:35 -080056 if (!checkCallingPermission(DUMP_PERMISSION)) {
57 ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP",
Yi Jinafb36062018-01-31 19:14:25 -080058 callingPid, callingUid);
Joe Onorato1754d742016-11-21 17:51:35 -080059 return Status::fromExceptionCode(Status::EX_SECURITY,
60 "Calling process does not have permission: android.permission.DUMP");
61 }
62 if (!checkCallingPermission(USAGE_STATS_PERMISSION)) {
63 ALOGW("Calling pid %d and uid %d does not have permission: android.permission.USAGE_STATS",
Yi Jinafb36062018-01-31 19:14:25 -080064 callingPid, callingUid);
Joe Onorato1754d742016-11-21 17:51:35 -080065 return Status::fromExceptionCode(Status::EX_SECURITY,
66 "Calling process does not have permission: android.permission.USAGE_STATS");
67 }
Yi Jin4bab3a12018-01-10 16:50:59 -080068
69 // checking calling request uid permission.
Yi Jin4bab3a12018-01-10 16:50:59 -080070 switch (args.dest()) {
71 case DEST_LOCAL:
Yi Jinafb36062018-01-31 19:14:25 -080072 if (callingUid != AID_SHELL && callingUid != AID_ROOT) {
73 ALOGW("Calling pid %d and uid %d does not have permission to get local data.",
74 callingPid, callingUid);
Yi Jin4bab3a12018-01-10 16:50:59 -080075 return Status::fromExceptionCode(Status::EX_SECURITY,
76 "Calling process does not have permission to get local data.");
77 }
78 case DEST_EXPLICIT:
Yi Jinafb36062018-01-31 19:14:25 -080079 if (callingUid != AID_SHELL && callingUid != AID_ROOT &&
80 callingUid != AID_STATSD && callingUid != AID_SYSTEM) {
81 ALOGW("Calling pid %d and uid %d does not have permission to get explicit data.",
82 callingPid, callingUid);
Yi Jin4bab3a12018-01-10 16:50:59 -080083 return Status::fromExceptionCode(Status::EX_SECURITY,
84 "Calling process does not have permission to get explicit data.");
85 }
86 }
Joe Onorato1754d742016-11-21 17:51:35 -080087 return Status::ok();
88}
Joe Onorato1754d742016-11-21 17:51:35 -080089// ================================================================================
90ReportRequestQueue::ReportRequestQueue()
91{
92}
93
94ReportRequestQueue::~ReportRequestQueue()
95{
96}
97
98void
Yi Jin4bab3a12018-01-10 16:50:59 -080099ReportRequestQueue::addRequest(const sp<ReportRequest>& request)
Joe Onorato1754d742016-11-21 17:51:35 -0800100{
101 unique_lock<mutex> lock(mLock);
102 mQueue.push_back(request);
103}
104
105sp<ReportRequest>
106ReportRequestQueue::getNextRequest()
107{
108 unique_lock<mutex> lock(mLock);
109 if (mQueue.empty()) {
110 return NULL;
111 } else {
112 sp<ReportRequest> front(mQueue.front());
113 mQueue.pop_front();
114 return front;
115 }
116}
117
118
119// ================================================================================
120ReportHandler::ReportHandler(const sp<Looper>& handlerLooper, const sp<ReportRequestQueue>& queue)
121 :mBacklogDelay(DEFAULT_BACKLOG_DELAY_NS),
122 mHandlerLooper(handlerLooper),
123 mQueue(queue)
124{
125}
126
127ReportHandler::~ReportHandler()
128{
129}
130
131void
132ReportHandler::handleMessage(const Message& message)
133{
134 switch (message.what) {
135 case WHAT_RUN_REPORT:
136 run_report();
137 break;
138 case WHAT_SEND_BACKLOG_TO_DROPBOX:
139 send_backlog_to_dropbox();
140 break;
141 }
142}
143
144void
145ReportHandler::scheduleRunReport(const sp<ReportRequest>& request)
146{
147 mQueue->addRequest(request);
148 mHandlerLooper->removeMessages(this, WHAT_RUN_REPORT);
149 mHandlerLooper->sendMessage(this, Message(WHAT_RUN_REPORT));
150}
151
152void
153ReportHandler::scheduleSendBacklogToDropbox()
154{
155 unique_lock<mutex> lock(mLock);
156 mBacklogDelay = DEFAULT_BACKLOG_DELAY_NS;
157 schedule_send_backlog_to_dropbox_locked();
158}
159
160void
161ReportHandler::schedule_send_backlog_to_dropbox_locked()
162{
163 mHandlerLooper->removeMessages(this, WHAT_SEND_BACKLOG_TO_DROPBOX);
164 mHandlerLooper->sendMessageDelayed(mBacklogDelay, this,
165 Message(WHAT_SEND_BACKLOG_TO_DROPBOX));
166}
167
168void
169ReportHandler::run_report()
170{
171 sp<Reporter> reporter = new Reporter();
172
173 // Merge all of the requests into one that has all of the
174 // requested fields.
175 while (true) {
176 sp<ReportRequest> request = mQueue->getNextRequest();
177 if (request == NULL) {
178 break;
179 }
180 reporter->batch.add(request);
Joe Onorato1754d742016-11-21 17:51:35 -0800181 }
182
183 // Take the report, which might take a while. More requests might queue
184 // up while we're doing this, and we'll handle them in their next batch.
185 // TODO: We should further rate-limit the reports to no more than N per time-period.
186 Reporter::run_report_status_t reportStatus = reporter->runReport();
187 if (reportStatus == Reporter::REPORT_NEEDS_DROPBOX) {
188 unique_lock<mutex> lock(mLock);
189 schedule_send_backlog_to_dropbox_locked();
190 }
191}
192
193void
194ReportHandler::send_backlog_to_dropbox()
195{
196 if (Reporter::upload_backlog() == Reporter::REPORT_NEEDS_DROPBOX) {
197 // There was a failure. Exponential backoff.
198 unique_lock<mutex> lock(mLock);
199 mBacklogDelay *= 2;
200 ALOGI("Error sending to dropbox. Trying again in %lld minutes",
201 (mBacklogDelay / (1000000000LL * 60)));
202 schedule_send_backlog_to_dropbox_locked();
203 } else {
204 mBacklogDelay = DEFAULT_BACKLOG_DELAY_NS;
205 }
206}
207
208// ================================================================================
209IncidentService::IncidentService(const sp<Looper>& handlerLooper)
210 :mQueue(new ReportRequestQueue())
211{
212 mHandler = new ReportHandler(handlerLooper, mQueue);
213}
214
215IncidentService::~IncidentService()
216{
217}
218
219Status
220IncidentService::reportIncident(const IncidentReportArgs& args)
221{
222 ALOGI("reportIncident");
223
Yi Jin4bab3a12018-01-10 16:50:59 -0800224 Status status = checkIncidentPermissions(args);
Joe Onorato1754d742016-11-21 17:51:35 -0800225 if (!status.isOk()) {
226 return status;
227 }
228
229 mHandler->scheduleRunReport(new ReportRequest(args, NULL, -1));
230
231 return Status::ok();
232}
233
234Status
235IncidentService::reportIncidentToStream(const IncidentReportArgs& args,
236 const sp<IIncidentReportStatusListener>& listener, const unique_fd& stream)
237{
238 ALOGI("reportIncidentToStream");
239
Yi Jin4bab3a12018-01-10 16:50:59 -0800240 Status status = checkIncidentPermissions(args);
Joe Onorato1754d742016-11-21 17:51:35 -0800241 if (!status.isOk()) {
242 return status;
243 }
244
245 int fd = dup(stream.get());
246 if (fd < 0) {
247 return Status::fromStatusT(-errno);
248 }
249
250 mHandler->scheduleRunReport(new ReportRequest(args, listener, fd));
251
252 return Status::ok();
253}
254
255Status
256IncidentService::systemRunning()
257{
258 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
259 return Status::fromExceptionCode(Status::EX_SECURITY,
260 "Only system uid can call systemRunning");
261 }
Yi Jinadd11e92017-07-30 16:10:07 -0700262
Joe Onorato1754d742016-11-21 17:51:35 -0800263 // When system_server is up and running, schedule the dropbox task to run.
264 mHandler->scheduleSendBacklogToDropbox();
265
266 return Status::ok();
267}
268