• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
checkIncidentPermissions()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 // ================================================================================
ReportRequestQueue()65 ReportRequestQueue::ReportRequestQueue()
66 {
67 }
68 
~ReportRequestQueue()69 ReportRequestQueue::~ReportRequestQueue()
70 {
71 }
72 
73 void
addRequest(const sp<ReportRequest> & request)74 ReportRequestQueue::addRequest(const sp<ReportRequest>& request)
75 {
76     unique_lock<mutex> lock(mLock);
77     mQueue.push_back(request);
78 }
79 
80 sp<ReportRequest>
getNextRequest()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 // ================================================================================
ReportHandler(const sp<Looper> & handlerLooper,const sp<ReportRequestQueue> & queue)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 
~ReportHandler()102 ReportHandler::~ReportHandler()
103 {
104 }
105 
106 void
handleMessage(const Message & message)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
scheduleRunReport(const sp<ReportRequest> & request)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
scheduleSendBacklogToDropbox()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
schedule_send_backlog_to_dropbox_locked()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
run_report()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
send_backlog_to_dropbox()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 // ================================================================================
IncidentService(const sp<Looper> & handlerLooper)185 IncidentService::IncidentService(const sp<Looper>& handlerLooper)
186     :mQueue(new ReportRequestQueue())
187 {
188     mHandler = new ReportHandler(handlerLooper, mQueue);
189 }
190 
~IncidentService()191 IncidentService::~IncidentService()
192 {
193 }
194 
195 Status
reportIncident(const IncidentReportArgs & args)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
reportIncidentToStream(const IncidentReportArgs & args,const sp<IIncidentReportStatusListener> & listener,const unique_fd & stream)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
systemRunning()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