blob: 4ba31b45e81cd693d334d7ec6c2a45486d86742a [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 */
Yi Jin4e843102018-02-14 15:36:18 -080016#define DEBUG false
Yi Jinb592e3b2018-02-01 15:17:04 -080017#include "Log.h"
Joe Onorato1754d742016-11-21 17:51:35 -080018
19#include "IncidentService.h"
20
Yi Jinb592e3b2018-02-01 15:17:04 -080021#include "FdBuffer.h"
Joe Onorato99598ee2019-02-11 15:55:13 +000022#include "PrivacyFilter.h"
Joe Onorato1754d742016-11-21 17:51:35 -080023#include "Reporter.h"
Yi Jinb592e3b2018-02-01 15:17:04 -080024#include "incidentd_util.h"
25#include "section_list.h"
Joe Onorato1754d742016-11-21 17:51:35 -080026
Mike Ma85434ec2018-11-27 10:32:31 -080027#include <android/os/IncidentReportArgs.h>
Joe Onorato1754d742016-11-21 17:51:35 -080028#include <binder/IPCThreadState.h>
Yi Jinb592e3b2018-02-01 15:17:04 -080029#include <binder/IResultReceiver.h>
Joe Onorato1754d742016-11-21 17:51:35 -080030#include <binder/IServiceManager.h>
Yi Jinb592e3b2018-02-01 15:17:04 -080031#include <binder/IShellCallback.h>
Mike Ma35056662018-12-06 13:32:59 -080032#include <log/log.h>
Joe Onorato1754d742016-11-21 17:51:35 -080033#include <private/android_filesystem_config.h>
34#include <utils/Looper.h>
35
36#include <unistd.h>
37
Joe Onorato99598ee2019-02-11 15:55:13 +000038enum {
39 WHAT_TAKE_REPORT = 1,
40 WHAT_SEND_BROADCASTS = 2
41};
Joe Onorato1754d742016-11-21 17:51:35 -080042
Joe Onorato99598ee2019-02-11 15:55:13 +000043#define DEFAULT_DELAY_NS (1000000000LL)
Joe Onorato1754d742016-11-21 17:51:35 -080044
Yi Jin4e843102018-02-14 15:36:18 -080045#define DEFAULT_BYTES_SIZE_LIMIT (20 * 1024 * 1024) // 20MB
46#define DEFAULT_REFACTORY_PERIOD_MS (24 * 60 * 60 * 1000) // 1 Day
47
Mike Ma28381692018-12-04 15:46:29 -080048// Skip these sections for dumpstate only. Dumpstate allows 10s max for each service to dump.
49// Skip logs (1100 - 1108) and traces (1200 - 1202) because they are already in the bug report.
50// Skip 3018 because it takes too long.
Mike Ma85434ec2018-11-27 10:32:31 -080051#define SKIPPED_SECTIONS { 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, /* Logs */ \
52 1200, 1201, 1202, /* Native, hal, java traces */ \
Mike Ma85434ec2018-11-27 10:32:31 -080053 3018 /* "meminfo -a --proto" */ }
54
Yi Jin6cacbcb2018-03-30 14:04:52 -070055namespace android {
56namespace os {
57namespace incidentd {
58
Joe Onorato99598ee2019-02-11 15:55:13 +000059String16 const APPROVE_INCIDENT_REPORTS("android.permission.APPROVE_INCIDENT_REPORTS");
Joe Onorato1754d742016-11-21 17:51:35 -080060String16 const DUMP_PERMISSION("android.permission.DUMP");
61String16 const USAGE_STATS_PERMISSION("android.permission.PACKAGE_USAGE_STATS");
62
Yi Jinb592e3b2018-02-01 15:17:04 -080063static Status checkIncidentPermissions(const IncidentReportArgs& args) {
Yi Jin437aa6e2018-01-10 11:34:26 -080064 uid_t callingUid = IPCThreadState::self()->getCallingUid();
Yi Jinafb36062018-01-31 19:14:25 -080065 pid_t callingPid = IPCThreadState::self()->getCallingPid();
Yi Jin437aa6e2018-01-10 11:34:26 -080066 if (callingUid == AID_ROOT || callingUid == AID_SHELL) {
Joe Onorato99598ee2019-02-11 15:55:13 +000067 // Root and shell are ok.
68 return Status::ok();
69 }
70
71 if (checkCallingPermission(APPROVE_INCIDENT_REPORTS)) {
72 // Permission controller (this is a singleton permission that is always granted
73 // exactly for PermissionController) is allowed to access incident reports
74 // so it can show the user info about what they are approving.
Yi Jin437aa6e2018-01-10 11:34:26 -080075 return Status::ok();
76 }
77
Yi Jin4bab3a12018-01-10 16:50:59 -080078 // checking calling permission.
Joe Onorato1754d742016-11-21 17:51:35 -080079 if (!checkCallingPermission(DUMP_PERMISSION)) {
80 ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP",
Yi Jinb592e3b2018-02-01 15:17:04 -080081 callingPid, callingUid);
82 return Status::fromExceptionCode(
83 Status::EX_SECURITY,
Joe Onorato1754d742016-11-21 17:51:35 -080084 "Calling process does not have permission: android.permission.DUMP");
85 }
86 if (!checkCallingPermission(USAGE_STATS_PERMISSION)) {
87 ALOGW("Calling pid %d and uid %d does not have permission: android.permission.USAGE_STATS",
Yi Jinb592e3b2018-02-01 15:17:04 -080088 callingPid, callingUid);
89 return Status::fromExceptionCode(
90 Status::EX_SECURITY,
Joe Onorato1754d742016-11-21 17:51:35 -080091 "Calling process does not have permission: android.permission.USAGE_STATS");
92 }
Yi Jin4bab3a12018-01-10 16:50:59 -080093
94 // checking calling request uid permission.
Joe Onorato99598ee2019-02-11 15:55:13 +000095 switch (args.getPrivacyPolicy()) {
96 case PRIVACY_POLICY_LOCAL:
Yi Jinafb36062018-01-31 19:14:25 -080097 if (callingUid != AID_SHELL && callingUid != AID_ROOT) {
98 ALOGW("Calling pid %d and uid %d does not have permission to get local data.",
Yi Jinb592e3b2018-02-01 15:17:04 -080099 callingPid, callingUid);
100 return Status::fromExceptionCode(
101 Status::EX_SECURITY,
102 "Calling process does not have permission to get local data.");
Yi Jin4bab3a12018-01-10 16:50:59 -0800103 }
Bookatzda9b8d02018-11-14 13:14:45 -0800104 break;
Joe Onorato99598ee2019-02-11 15:55:13 +0000105 case PRIVACY_POLICY_EXPLICIT:
Yi Jinb592e3b2018-02-01 15:17:04 -0800106 if (callingUid != AID_SHELL && callingUid != AID_ROOT && callingUid != AID_STATSD &&
Bookatzda9b8d02018-11-14 13:14:45 -0800107 callingUid != AID_SYSTEM) {
Yi Jinafb36062018-01-31 19:14:25 -0800108 ALOGW("Calling pid %d and uid %d does not have permission to get explicit data.",
Yi Jinb592e3b2018-02-01 15:17:04 -0800109 callingPid, callingUid);
110 return Status::fromExceptionCode(
111 Status::EX_SECURITY,
112 "Calling process does not have permission to get explicit data.");
Yi Jin4bab3a12018-01-10 16:50:59 -0800113 }
Bookatzda9b8d02018-11-14 13:14:45 -0800114 break;
Yi Jin4bab3a12018-01-10 16:50:59 -0800115 }
Joe Onorato1754d742016-11-21 17:51:35 -0800116 return Status::ok();
117}
Yi Jin6cacbcb2018-03-30 14:04:52 -0700118
Joe Onorato99598ee2019-02-11 15:55:13 +0000119static string build_uri(const string& pkg, const string& cls, const string& id) {
120 return "build_uri not implemented " + pkg + "/" + cls + "/" + id;
Joe Onorato1754d742016-11-21 17:51:35 -0800121}
122
Joe Onorato1754d742016-11-21 17:51:35 -0800123// ================================================================================
Joe Onorato99598ee2019-02-11 15:55:13 +0000124ReportHandler::ReportHandler(const sp<WorkDirectory>& workDirectory,
125 const sp<Broadcaster>& broadcaster, const sp<Looper>& handlerLooper,
126 const sp<Throttler>& throttler)
127 :mLock(),
128 mWorkDirectory(workDirectory),
129 mBroadcaster(broadcaster),
130 mHandlerLooper(handlerLooper),
131 mBacklogDelay(DEFAULT_DELAY_NS),
132 mThrottler(throttler),
133 mBatch(new ReportBatch()) {
134}
Joe Onorato1754d742016-11-21 17:51:35 -0800135
Joe Onorato99598ee2019-02-11 15:55:13 +0000136ReportHandler::~ReportHandler() {
137}
Joe Onorato1754d742016-11-21 17:51:35 -0800138
Yi Jinb592e3b2018-02-01 15:17:04 -0800139void ReportHandler::handleMessage(const Message& message) {
Joe Onorato1754d742016-11-21 17:51:35 -0800140 switch (message.what) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000141 case WHAT_TAKE_REPORT:
142 take_report();
Joe Onorato1754d742016-11-21 17:51:35 -0800143 break;
Joe Onorato99598ee2019-02-11 15:55:13 +0000144 case WHAT_SEND_BROADCASTS:
145 send_broadcasts();
Joe Onorato1754d742016-11-21 17:51:35 -0800146 break;
147 }
148}
149
Joe Onorato99598ee2019-02-11 15:55:13 +0000150void ReportHandler::schedulePersistedReport(const IncidentReportArgs& args) {
151 mBatch->addPersistedReport(args);
152 mHandlerLooper->removeMessages(this, WHAT_TAKE_REPORT);
153 mHandlerLooper->sendMessage(this, Message(WHAT_TAKE_REPORT));
Joe Onorato1754d742016-11-21 17:51:35 -0800154}
155
Joe Onorato99598ee2019-02-11 15:55:13 +0000156void ReportHandler::scheduleStreamingReport(const IncidentReportArgs& args,
157 const sp<IIncidentReportStatusListener>& listener, int streamFd) {
158 mBatch->addStreamingReport(args, listener, streamFd);
159 mHandlerLooper->removeMessages(this, WHAT_TAKE_REPORT);
160 mHandlerLooper->sendMessage(this, Message(WHAT_TAKE_REPORT));
161}
162
163void ReportHandler::scheduleSendBacklog() {
Joe Onorato1754d742016-11-21 17:51:35 -0800164 unique_lock<mutex> lock(mLock);
Joe Onorato99598ee2019-02-11 15:55:13 +0000165 mBacklogDelay = DEFAULT_DELAY_NS;
166 schedule_send_broadcasts_locked();
Joe Onorato1754d742016-11-21 17:51:35 -0800167}
168
Joe Onorato99598ee2019-02-11 15:55:13 +0000169void ReportHandler::schedule_send_broadcasts_locked() {
170 mHandlerLooper->removeMessages(this, WHAT_SEND_BROADCASTS);
171 mHandlerLooper->sendMessageDelayed(mBacklogDelay, this, Message(WHAT_SEND_BROADCASTS));
Joe Onorato1754d742016-11-21 17:51:35 -0800172}
173
Joe Onorato99598ee2019-02-11 15:55:13 +0000174void ReportHandler::take_report() {
175 // Cycle the batch
176 sp<ReportBatch> batch;
177 {
178 unique_lock<mutex> lock(mLock);
179 batch = mBatch;
180 mBatch = new ReportBatch();
Joe Onorato1754d742016-11-21 17:51:35 -0800181 }
182
Joe Onorato99598ee2019-02-11 15:55:13 +0000183 if (batch->empty()) {
184 // Nothing to do.
185 return;
186 }
187
188 sp<Reporter> reporter = new Reporter(mWorkDirectory, batch);
189
190 // TODO: Do we really want to clear the reports if we throttle? Should we only throttle
191 // requests going to dropbox? How do we reconcile throttling with testing?
Yi Jin4e843102018-02-14 15:36:18 -0800192 if (mThrottler->shouldThrottle()) {
193 ALOGW("RunReport got throttled.");
194 return;
195 }
196
Joe Onorato1754d742016-11-21 17:51:35 -0800197 // Take the report, which might take a while. More requests might queue
198 // up while we're doing this, and we'll handle them in their next batch.
199 // TODO: We should further rate-limit the reports to no more than N per time-period.
Joe Onorato99598ee2019-02-11 15:55:13 +0000200 // TODO: Move this inside reporter.
Yi Jin4e843102018-02-14 15:36:18 -0800201 size_t reportByteSize = 0;
Joe Onorato99598ee2019-02-11 15:55:13 +0000202 reporter->runReport(&reportByteSize);
203
Yi Jin4e843102018-02-14 15:36:18 -0800204 mThrottler->addReportSize(reportByteSize);
Joe Onorato99598ee2019-02-11 15:55:13 +0000205
206 // Kick off the next steps, one of which is to send any new or otherwise remaining
207 // approvals, and one of which is to send any new or remaining broadcasts.
208 {
Joe Onorato1754d742016-11-21 17:51:35 -0800209 unique_lock<mutex> lock(mLock);
Joe Onorato99598ee2019-02-11 15:55:13 +0000210 schedule_send_broadcasts_locked();
Joe Onorato1754d742016-11-21 17:51:35 -0800211 }
212}
213
Joe Onorato99598ee2019-02-11 15:55:13 +0000214void ReportHandler::send_broadcasts() {
215 Broadcaster::broadcast_status_t result = mBroadcaster->sendBroadcasts();
216 if (result == Broadcaster::BROADCASTS_FINISHED) {
217 // We're done.
218 unique_lock<mutex> lock(mLock);
219 mBacklogDelay = DEFAULT_DELAY_NS;
220 } else if (result == Broadcaster::BROADCASTS_REPEAT) {
221 // It worked, but there are more.
222 unique_lock<mutex> lock(mLock);
223 mBacklogDelay = DEFAULT_DELAY_NS;
224 schedule_send_broadcasts_locked();
225 } else if (result == Broadcaster::BROADCASTS_BACKOFF) {
Joe Onorato1754d742016-11-21 17:51:35 -0800226 // There was a failure. Exponential backoff.
227 unique_lock<mutex> lock(mLock);
228 mBacklogDelay *= 2;
229 ALOGI("Error sending to dropbox. Trying again in %lld minutes",
Yi Jinb592e3b2018-02-01 15:17:04 -0800230 (mBacklogDelay / (1000000000LL * 60)));
Joe Onorato99598ee2019-02-11 15:55:13 +0000231 schedule_send_broadcasts_locked();
Joe Onorato1754d742016-11-21 17:51:35 -0800232 }
233}
234
235// ================================================================================
Joe Onorato99598ee2019-02-11 15:55:13 +0000236IncidentService::IncidentService(const sp<Looper>& handlerLooper) {
237 mThrottler = new Throttler(DEFAULT_BYTES_SIZE_LIMIT, DEFAULT_REFACTORY_PERIOD_MS);
238 mWorkDirectory = new WorkDirectory();
239 mBroadcaster = new Broadcaster(mWorkDirectory);
240 mHandler = new ReportHandler(mWorkDirectory, mBroadcaster, handlerLooper,
241 mThrottler);
242 mBroadcaster->setHandler(mHandler);
Joe Onorato1754d742016-11-21 17:51:35 -0800243}
244
Yi Jinb592e3b2018-02-01 15:17:04 -0800245IncidentService::~IncidentService() {}
Joe Onorato1754d742016-11-21 17:51:35 -0800246
Yi Jinb592e3b2018-02-01 15:17:04 -0800247Status IncidentService::reportIncident(const IncidentReportArgs& args) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000248 // TODO: Validate that the privacy policy is one of the real ones.
249 // If it isn't, clamp it to the next more restrictive real one.
Joe Onorato1754d742016-11-21 17:51:35 -0800250
Joe Onorato99598ee2019-02-11 15:55:13 +0000251 // TODO: This function should reject the LOCAL privacy policy.
252 // Those have to stream.
253
254 // TODO: Check that the broadcast recevier has the proper permissions
255 // TODO: Maybe we should consider relaxing the permissions if it's going to
256 // dropbox, but definitely not if it's going to the broadcaster.
Yi Jin4bab3a12018-01-10 16:50:59 -0800257 Status status = checkIncidentPermissions(args);
Joe Onorato1754d742016-11-21 17:51:35 -0800258 if (!status.isOk()) {
259 return status;
260 }
261
Joe Onorato99598ee2019-02-11 15:55:13 +0000262 // If they didn't specify a component, use dropbox.
263 IncidentReportArgs argsCopy(args);
264 if (argsCopy.receiverPkg().length() == 0 && argsCopy.receiverCls().length() == 0) {
265 argsCopy.setReceiverPkg(DROPBOX_SENTINEL.getPackageName());
266 argsCopy.setReceiverCls(DROPBOX_SENTINEL.getClassName());
267 }
268
269 mHandler->schedulePersistedReport(argsCopy);
Joe Onorato1754d742016-11-21 17:51:35 -0800270
271 return Status::ok();
272}
273
Yi Jinb592e3b2018-02-01 15:17:04 -0800274Status IncidentService::reportIncidentToStream(const IncidentReportArgs& args,
275 const sp<IIncidentReportStatusListener>& listener,
276 const unique_fd& stream) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000277 // TODO: Validate that the privacy policy is one of the real ones.
278 // If it isn't, clamp it to the next more restrictive real one.
Joe Onorato1754d742016-11-21 17:51:35 -0800279
Joe Onorato99598ee2019-02-11 15:55:13 +0000280 // TODO: Only shell should be able to do a LOCAL privacy policy report.
281
282 // Streaming reports can not also be broadcast.
283 IncidentReportArgs argsCopy(args);
284 argsCopy.setReceiverPkg("");
285 argsCopy.setReceiverCls("");
286
287 Status status = checkIncidentPermissions(argsCopy);
Joe Onorato1754d742016-11-21 17:51:35 -0800288 if (!status.isOk()) {
289 return status;
290 }
291
Joe Onorato99598ee2019-02-11 15:55:13 +0000292
293 // The ReportRequest takes ownership of the fd, so we need to dup it.
Joe Onorato1754d742016-11-21 17:51:35 -0800294 int fd = dup(stream.get());
295 if (fd < 0) {
296 return Status::fromStatusT(-errno);
297 }
298
Joe Onorato99598ee2019-02-11 15:55:13 +0000299 mHandler->scheduleStreamingReport(argsCopy, listener, fd);
Joe Onorato1754d742016-11-21 17:51:35 -0800300
301 return Status::ok();
302}
303
Yi Jinb592e3b2018-02-01 15:17:04 -0800304Status IncidentService::systemRunning() {
Joe Onorato1754d742016-11-21 17:51:35 -0800305 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
306 return Status::fromExceptionCode(Status::EX_SECURITY,
Yi Jinb592e3b2018-02-01 15:17:04 -0800307 "Only system uid can call systemRunning");
Joe Onorato1754d742016-11-21 17:51:35 -0800308 }
Yi Jinadd11e92017-07-30 16:10:07 -0700309
Joe Onorato1754d742016-11-21 17:51:35 -0800310 // When system_server is up and running, schedule the dropbox task to run.
Joe Onorato99598ee2019-02-11 15:55:13 +0000311 mBroadcaster->reset();
312 mHandler->scheduleSendBacklog();
313
314 return Status::ok();
315}
316
317Status IncidentService::getIncidentReportList(const String16& pkg16, const String16& cls16,
318 vector<String16>* result) {
319 status_t err;
320 const string pkg(String8(pkg16).string());
321 const string cls(String8(cls16).string());
322
323 // List the reports
324 vector<sp<ReportFile>> all;
325 err = mWorkDirectory->getReports(&all, 0);
326 if (err != NO_ERROR) {
327 return Status::fromStatusT(err);
328 }
329
330 // Find the ones that match pkg and cls.
331 for (sp<ReportFile>& file: all) {
332 err = file->loadEnvelope();
333 if (err != NO_ERROR) {
334 continue;
335 }
336 const ReportFileProto& envelope = file->getEnvelope();
337 size_t reportCount = envelope.report_size();
338 for (int reportIndex = 0; reportIndex < reportCount; reportIndex++) {
339 const ReportFileProto_Report& report = envelope.report(reportIndex);
340 if (pkg == report.pkg() && cls == report.cls()) {
341 result->push_back(String16(build_uri(pkg, cls, file->getId()).c_str()));
342 break;
343 }
344 }
345 }
346
347 return Status::ok();
348}
349
350Status IncidentService::getIncidentReport(const String16& pkg16, const String16& cls16,
351 const String16& id16, IncidentManager::IncidentReport* result) {
352 status_t err;
353
354 const string pkg(String8(pkg16).string());
355 const string cls(String8(cls16).string());
356 const string id(String8(id16).string());
357
358 IncidentReportArgs args;
359 sp<ReportFile> file = mWorkDirectory->getReport(pkg, cls, id, &args);
360 if (file != nullptr) {
361 int fd;
362 err = file->startFilteringData(&fd, args);
363 if (err != 0) {
364 ALOGW("Error reading data file that we think should exist: %s",
365 file->getDataFileName().c_str());
366 return Status::ok();
367 }
368
369 result->setTimestampNs(file->getTimestampNs());
370 result->setPrivacyPolicy(file->getEnvelope().privacy_policy());
371 result->takeFileDescriptor(fd);
372 }
373
374 return Status::ok();
375}
376
377Status IncidentService::deleteIncidentReports(const String16& pkg16, const String16& cls16,
378 const String16& id16) {
379 const string pkg(String8(pkg16).string());
380 const string cls(String8(cls16).string());
381 const string id(String8(id16).string());
382
383 sp<ReportFile> file = mWorkDirectory->getReport(pkg, cls, id, nullptr);
384 if (file != nullptr) {
385 mWorkDirectory->commit(file, pkg, cls);
386 }
387 mBroadcaster->clearBroadcasts(pkg, cls, id);
388
389 return Status::ok();
390}
391
392Status IncidentService::deleteAllIncidentReports(const String16& pkg16) {
393 const string pkg(String8(pkg16).string());
394
395 mWorkDirectory->commitAll(pkg);
396 mBroadcaster->clearPackageBroadcasts(pkg);
Joe Onorato1754d742016-11-21 17:51:35 -0800397
398 return Status::ok();
399}
400
Yi Jinb592e3b2018-02-01 15:17:04 -0800401/**
402 * Implement our own because the default binder implementation isn't
403 * properly handling SHELL_COMMAND_TRANSACTION.
404 */
405status_t IncidentService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
406 uint32_t flags) {
407 status_t err;
408
409 switch (code) {
410 case SHELL_COMMAND_TRANSACTION: {
411 int in = data.readFileDescriptor();
412 int out = data.readFileDescriptor();
413 int err = data.readFileDescriptor();
414 int argc = data.readInt32();
415 Vector<String8> args;
416 for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
417 args.add(String8(data.readString16()));
418 }
419 sp<IShellCallback> shellCallback = IShellCallback::asInterface(data.readStrongBinder());
420 sp<IResultReceiver> resultReceiver =
421 IResultReceiver::asInterface(data.readStrongBinder());
422
423 FILE* fin = fdopen(in, "r");
424 FILE* fout = fdopen(out, "w");
425 FILE* ferr = fdopen(err, "w");
426
427 if (fin == NULL || fout == NULL || ferr == NULL) {
428 resultReceiver->send(NO_MEMORY);
429 } else {
430 err = command(fin, fout, ferr, args);
431 resultReceiver->send(err);
432 }
433
434 if (fin != NULL) {
435 fflush(fin);
436 fclose(fin);
437 }
438 if (fout != NULL) {
439 fflush(fout);
440 fclose(fout);
441 }
442 if (fout != NULL) {
443 fflush(ferr);
444 fclose(ferr);
445 }
446
447 return NO_ERROR;
Bookatzda9b8d02018-11-14 13:14:45 -0800448 } break;
Yi Jinb592e3b2018-02-01 15:17:04 -0800449 default: { return BnIncidentManager::onTransact(code, data, reply, flags); }
450 }
451}
452
453status_t IncidentService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
454 const int argCount = args.size();
455
456 if (argCount >= 1) {
457 if (!args[0].compare(String8("privacy"))) {
458 return cmd_privacy(in, out, err, args);
459 }
Yi Jin4e843102018-02-14 15:36:18 -0800460 if (!args[0].compare(String8("throttler"))) {
461 mThrottler->dump(out);
462 return NO_ERROR;
463 }
Yi Jin908c02f2018-06-22 16:51:40 -0700464 if (!args[0].compare(String8("section"))) {
465 int id = atoi(args[1]);
466 int idx = 0;
467 while (SECTION_LIST[idx] != NULL) {
468 const Section* section = SECTION_LIST[idx];
469 if (section->id == id) {
470 fprintf(out, "Section[%d] %s\n", id, section->name.string());
471 break;
472 }
473 idx++;
474 }
475 return NO_ERROR;
476 }
Yi Jinb592e3b2018-02-01 15:17:04 -0800477 }
478 return cmd_help(out);
479}
480
481status_t IncidentService::cmd_help(FILE* out) {
482 fprintf(out, "usage: adb shell cmd incident privacy print <section_id>\n");
483 fprintf(out, "usage: adb shell cmd incident privacy parse <section_id> < proto.txt\n");
Yi Jin908c02f2018-06-22 16:51:40 -0700484 fprintf(out, " Prints/parses for the section id.\n\n");
485 fprintf(out, "usage: adb shell cmd incident section <section_id>\n");
486 fprintf(out, " Prints section id and its name.\n\n");
Yi Jin4e843102018-02-14 15:36:18 -0800487 fprintf(out, "usage: adb shell cmd incident throttler\n");
488 fprintf(out, " Prints the current throttler state\n");
Yi Jinb592e3b2018-02-01 15:17:04 -0800489 return NO_ERROR;
490}
491
492static void printPrivacy(const Privacy* p, FILE* out, String8 indent) {
493 if (p == NULL) return;
Joe Onorato99598ee2019-02-11 15:55:13 +0000494 fprintf(out, "%sid:%d, type:%d, dest:%d\n", indent.string(), p->field_id, p->type, p->policy);
Yi Jinb592e3b2018-02-01 15:17:04 -0800495 if (p->children == NULL) return;
496 for (int i = 0; p->children[i] != NULL; i++) { // NULL-terminated.
497 printPrivacy(p->children[i], out, indent + " ");
498 }
499}
500
501status_t IncidentService::cmd_privacy(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000502 (void)in;
503
Yi Jinb592e3b2018-02-01 15:17:04 -0800504 const int argCount = args.size();
505 if (argCount >= 3) {
506 String8 opt = args[1];
507 int sectionId = atoi(args[2].string());
508
509 const Privacy* p = get_privacy_of_section(sectionId);
510 if (p == NULL) {
511 fprintf(err, "Can't find section id %d\n", sectionId);
512 return NO_ERROR;
513 }
514 fprintf(err, "Get privacy for %d\n", sectionId);
515 if (opt == "print") {
516 printPrivacy(p, out, String8(""));
517 } else if (opt == "parse") {
Joe Onorato99598ee2019-02-11 15:55:13 +0000518 /*
Yi Jinb592e3b2018-02-01 15:17:04 -0800519 FdBuffer buf;
Yi Jine3dab2d2018-03-22 16:56:39 -0700520 status_t error = buf.read(fileno(in), 60000);
Yi Jinb592e3b2018-02-01 15:17:04 -0800521 if (error != NO_ERROR) {
522 fprintf(err, "Error reading from stdin\n");
523 return error;
524 }
525 fprintf(err, "Read %zu bytes\n", buf.size());
Joe Onorato99598ee2019-02-11 15:55:13 +0000526 PrivacyFilter pBuf(p, buf.data());
Yi Jinb592e3b2018-02-01 15:17:04 -0800527
528 PrivacySpec spec = PrivacySpec::new_spec(argCount > 3 ? atoi(args[3]) : -1);
529 error = pBuf.strip(spec);
530 if (error != NO_ERROR) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000531 fprintf(err, "Error strip pii fields with spec %d\n", spec.policy);
Yi Jinb592e3b2018-02-01 15:17:04 -0800532 return error;
533 }
534 return pBuf.flush(fileno(out));
Joe Onorato99598ee2019-02-11 15:55:13 +0000535 */
536 return -1;
Yi Jinb592e3b2018-02-01 15:17:04 -0800537 }
538 } else {
539 return cmd_help(out);
540 }
541 return NO_ERROR;
542}
Yi Jin6cacbcb2018-03-30 14:04:52 -0700543
Mike Ma85434ec2018-11-27 10:32:31 -0800544status_t IncidentService::dump(int fd, const Vector<String16>& args) {
545 if (std::find(args.begin(), args.end(), String16("--proto")) == args.end()) {
546 ALOGD("Skip dumping incident. Only proto format is supported.");
547 dprintf(fd, "Incident dump only supports proto version.\n");
548 return NO_ERROR;
549 }
550
551 ALOGD("Dump incident proto");
552 IncidentReportArgs incidentArgs;
Joe Onorato99598ee2019-02-11 15:55:13 +0000553 incidentArgs.setPrivacyPolicy(PRIVACY_POLICY_EXPLICIT);
Mike Ma85434ec2018-11-27 10:32:31 -0800554 int skipped[] = SKIPPED_SECTIONS;
555 for (const Section** section = SECTION_LIST; *section; section++) {
556 const int id = (*section)->id;
557 if (std::find(std::begin(skipped), std::end(skipped), id) == std::end(skipped)) {
558 incidentArgs.addSection(id);
559 }
560 }
561
562 if (!checkIncidentPermissions(incidentArgs).isOk()) {
563 return PERMISSION_DENIED;
564 }
565
Joe Onorato99598ee2019-02-11 15:55:13 +0000566 // The ReportRequest takes ownership of the fd, so we need to dup it.
Mike Ma85434ec2018-11-27 10:32:31 -0800567 int fd1 = dup(fd);
568 if (fd1 < 0) {
569 return -errno;
570 }
571
Joe Onorato99598ee2019-02-11 15:55:13 +0000572 // TODO: Remove this. Someone even dumpstate, wanting to get an incident report
573 // should use the API. That will take making dumpstated call the API, which is a
574 // good thing. It also means it won't be subject to the timeout.
575 mHandler->scheduleStreamingReport(incidentArgs, NULL, fd1);
Mike Ma85434ec2018-11-27 10:32:31 -0800576
577 return NO_ERROR;
578}
579
Yi Jin6cacbcb2018-03-30 14:04:52 -0700580} // namespace incidentd
581} // namespace os
582} // namespace android