blob: 1d5ab59f9ba81192697429cb583d97a9693c03d2 [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();
49 if (callingUid == AID_ROOT || callingUid == AID_SHELL) {
50 // root doesn't have permission.DUMP if don't do this!
51 return Status::ok();
52 }
53
Yi Jin4bab3a12018-01-10 16:50:59 -080054 // checking calling permission.
Joe Onorato1754d742016-11-21 17:51:35 -080055 if (!checkCallingPermission(DUMP_PERMISSION)) {
56 ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP",
Yi Jin437aa6e2018-01-10 11:34:26 -080057 IPCThreadState::self()->getCallingPid(), callingUid);
Joe Onorato1754d742016-11-21 17:51:35 -080058 return Status::fromExceptionCode(Status::EX_SECURITY,
59 "Calling process does not have permission: android.permission.DUMP");
60 }
61 if (!checkCallingPermission(USAGE_STATS_PERMISSION)) {
62 ALOGW("Calling pid %d and uid %d does not have permission: android.permission.USAGE_STATS",
Yi Jin437aa6e2018-01-10 11:34:26 -080063 IPCThreadState::self()->getCallingPid(), callingUid);
Joe Onorato1754d742016-11-21 17:51:35 -080064 return Status::fromExceptionCode(Status::EX_SECURITY,
65 "Calling process does not have permission: android.permission.USAGE_STATS");
66 }
Yi Jin4bab3a12018-01-10 16:50:59 -080067
68 // checking calling request uid permission.
Yi Jin4bab3a12018-01-10 16:50:59 -080069 switch (args.dest()) {
70 case DEST_LOCAL:
71 if (callingUid != AID_SHELL || callingUid != AID_ROOT) {
72 return Status::fromExceptionCode(Status::EX_SECURITY,
73 "Calling process does not have permission to get local data.");
74 }
75 case DEST_EXPLICIT:
76 if (callingUid != AID_SHELL || callingUid != AID_ROOT ||
77 callingUid != AID_STATSD || callingUid != AID_SYSTEM) {
78 return Status::fromExceptionCode(Status::EX_SECURITY,
79 "Calling process does not have permission to get explicit data.");
80 }
81 }
Joe Onorato1754d742016-11-21 17:51:35 -080082 return Status::ok();
83}
Joe Onorato1754d742016-11-21 17:51:35 -080084// ================================================================================
85ReportRequestQueue::ReportRequestQueue()
86{
87}
88
89ReportRequestQueue::~ReportRequestQueue()
90{
91}
92
93void
Yi Jin4bab3a12018-01-10 16:50:59 -080094ReportRequestQueue::addRequest(const sp<ReportRequest>& request)
Joe Onorato1754d742016-11-21 17:51:35 -080095{
96 unique_lock<mutex> lock(mLock);
97 mQueue.push_back(request);
98}
99
100sp<ReportRequest>
101ReportRequestQueue::getNextRequest()
102{
103 unique_lock<mutex> lock(mLock);
104 if (mQueue.empty()) {
105 return NULL;
106 } else {
107 sp<ReportRequest> front(mQueue.front());
108 mQueue.pop_front();
109 return front;
110 }
111}
112
113
114// ================================================================================
115ReportHandler::ReportHandler(const sp<Looper>& handlerLooper, const sp<ReportRequestQueue>& queue)
116 :mBacklogDelay(DEFAULT_BACKLOG_DELAY_NS),
117 mHandlerLooper(handlerLooper),
118 mQueue(queue)
119{
120}
121
122ReportHandler::~ReportHandler()
123{
124}
125
126void
127ReportHandler::handleMessage(const Message& message)
128{
129 switch (message.what) {
130 case WHAT_RUN_REPORT:
131 run_report();
132 break;
133 case WHAT_SEND_BACKLOG_TO_DROPBOX:
134 send_backlog_to_dropbox();
135 break;
136 }
137}
138
139void
140ReportHandler::scheduleRunReport(const sp<ReportRequest>& request)
141{
142 mQueue->addRequest(request);
143 mHandlerLooper->removeMessages(this, WHAT_RUN_REPORT);
144 mHandlerLooper->sendMessage(this, Message(WHAT_RUN_REPORT));
145}
146
147void
148ReportHandler::scheduleSendBacklogToDropbox()
149{
150 unique_lock<mutex> lock(mLock);
151 mBacklogDelay = DEFAULT_BACKLOG_DELAY_NS;
152 schedule_send_backlog_to_dropbox_locked();
153}
154
155void
156ReportHandler::schedule_send_backlog_to_dropbox_locked()
157{
158 mHandlerLooper->removeMessages(this, WHAT_SEND_BACKLOG_TO_DROPBOX);
159 mHandlerLooper->sendMessageDelayed(mBacklogDelay, this,
160 Message(WHAT_SEND_BACKLOG_TO_DROPBOX));
161}
162
163void
164ReportHandler::run_report()
165{
166 sp<Reporter> reporter = new Reporter();
167
168 // Merge all of the requests into one that has all of the
169 // requested fields.
170 while (true) {
171 sp<ReportRequest> request = mQueue->getNextRequest();
172 if (request == NULL) {
173 break;
174 }
175 reporter->batch.add(request);
Joe Onorato1754d742016-11-21 17:51:35 -0800176 }
177
178 // Take the report, which might take a while. More requests might queue
179 // up while we're doing this, and we'll handle them in their next batch.
180 // TODO: We should further rate-limit the reports to no more than N per time-period.
181 Reporter::run_report_status_t reportStatus = reporter->runReport();
182 if (reportStatus == Reporter::REPORT_NEEDS_DROPBOX) {
183 unique_lock<mutex> lock(mLock);
184 schedule_send_backlog_to_dropbox_locked();
185 }
186}
187
188void
189ReportHandler::send_backlog_to_dropbox()
190{
191 if (Reporter::upload_backlog() == Reporter::REPORT_NEEDS_DROPBOX) {
192 // There was a failure. Exponential backoff.
193 unique_lock<mutex> lock(mLock);
194 mBacklogDelay *= 2;
195 ALOGI("Error sending to dropbox. Trying again in %lld minutes",
196 (mBacklogDelay / (1000000000LL * 60)));
197 schedule_send_backlog_to_dropbox_locked();
198 } else {
199 mBacklogDelay = DEFAULT_BACKLOG_DELAY_NS;
200 }
201}
202
203// ================================================================================
204IncidentService::IncidentService(const sp<Looper>& handlerLooper)
205 :mQueue(new ReportRequestQueue())
206{
207 mHandler = new ReportHandler(handlerLooper, mQueue);
208}
209
210IncidentService::~IncidentService()
211{
212}
213
214Status
215IncidentService::reportIncident(const IncidentReportArgs& args)
216{
217 ALOGI("reportIncident");
218
Yi Jin4bab3a12018-01-10 16:50:59 -0800219 Status status = checkIncidentPermissions(args);
Joe Onorato1754d742016-11-21 17:51:35 -0800220 if (!status.isOk()) {
221 return status;
222 }
223
224 mHandler->scheduleRunReport(new ReportRequest(args, NULL, -1));
225
226 return Status::ok();
227}
228
229Status
230IncidentService::reportIncidentToStream(const IncidentReportArgs& args,
231 const sp<IIncidentReportStatusListener>& listener, const unique_fd& stream)
232{
233 ALOGI("reportIncidentToStream");
234
Yi Jin4bab3a12018-01-10 16:50:59 -0800235 Status status = checkIncidentPermissions(args);
Joe Onorato1754d742016-11-21 17:51:35 -0800236 if (!status.isOk()) {
237 return status;
238 }
239
240 int fd = dup(stream.get());
241 if (fd < 0) {
242 return Status::fromStatusT(-errno);
243 }
244
245 mHandler->scheduleRunReport(new ReportRequest(args, listener, fd));
246
247 return Status::ok();
248}
249
250Status
251IncidentService::systemRunning()
252{
253 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
254 return Status::fromExceptionCode(Status::EX_SECURITY,
255 "Only system uid can call systemRunning");
256 }
Yi Jinadd11e92017-07-30 16:10:07 -0700257
Joe Onorato1754d742016-11-21 17:51:35 -0800258 // When system_server is up and running, schedule the dropbox task to run.
259 mHandler->scheduleSendBacklogToDropbox();
260
261 return Status::ok();
262}
263