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