1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker *
4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker *
8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker *
10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker */
16*d57664e9SAndroid Build Coastguard Worker #define DEBUG false
17*d57664e9SAndroid Build Coastguard Worker #include "Log.h"
18*d57664e9SAndroid Build Coastguard Worker
19*d57664e9SAndroid Build Coastguard Worker #include "IncidentService.h"
20*d57664e9SAndroid Build Coastguard Worker
21*d57664e9SAndroid Build Coastguard Worker #include "FdBuffer.h"
22*d57664e9SAndroid Build Coastguard Worker #include "PrivacyFilter.h"
23*d57664e9SAndroid Build Coastguard Worker #include "Reporter.h"
24*d57664e9SAndroid Build Coastguard Worker #include "incidentd_util.h"
25*d57664e9SAndroid Build Coastguard Worker #include "section_list.h"
26*d57664e9SAndroid Build Coastguard Worker
27*d57664e9SAndroid Build Coastguard Worker #include <android/os/IncidentReportArgs.h>
28*d57664e9SAndroid Build Coastguard Worker #include <binder/IPCThreadState.h>
29*d57664e9SAndroid Build Coastguard Worker #include <binder/IResultReceiver.h>
30*d57664e9SAndroid Build Coastguard Worker #include <binder/IServiceManager.h>
31*d57664e9SAndroid Build Coastguard Worker #include <binder/IShellCallback.h>
32*d57664e9SAndroid Build Coastguard Worker #include <log/log.h>
33*d57664e9SAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
34*d57664e9SAndroid Build Coastguard Worker #include <utils/Looper.h>
35*d57664e9SAndroid Build Coastguard Worker #include <thread>
36*d57664e9SAndroid Build Coastguard Worker
37*d57664e9SAndroid Build Coastguard Worker #include <unistd.h>
38*d57664e9SAndroid Build Coastguard Worker
39*d57664e9SAndroid Build Coastguard Worker enum {
40*d57664e9SAndroid Build Coastguard Worker WHAT_TAKE_REPORT = 1,
41*d57664e9SAndroid Build Coastguard Worker WHAT_SEND_BROADCASTS = 2
42*d57664e9SAndroid Build Coastguard Worker };
43*d57664e9SAndroid Build Coastguard Worker
44*d57664e9SAndroid Build Coastguard Worker #define DEFAULT_DELAY_NS (1000000000LL)
45*d57664e9SAndroid Build Coastguard Worker
46*d57664e9SAndroid Build Coastguard Worker #define DEFAULT_BYTES_SIZE_LIMIT (400 * 1024 * 1024) // 400MB
47*d57664e9SAndroid Build Coastguard Worker #define DEFAULT_REFACTORY_PERIOD_MS (24 * 60 * 60 * 1000) // 1 Day
48*d57664e9SAndroid Build Coastguard Worker
49*d57664e9SAndroid Build Coastguard Worker // Skip these sections (for dumpstate only)
50*d57664e9SAndroid Build Coastguard Worker // Skip logs (1100 - 1108), traces (1200 - 1202), dumpsys (3000 - 3024, 3027 - 3056, 4000 - 4001)
51*d57664e9SAndroid Build Coastguard Worker // because they are already in the bug report.
52*d57664e9SAndroid Build Coastguard Worker #define SKIPPED_DUMPSTATE_SECTIONS { \
53*d57664e9SAndroid Build Coastguard Worker 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, /* Logs */ \
54*d57664e9SAndroid Build Coastguard Worker 1200, 1201, 1202, /* Native, hal, java traces */ \
55*d57664e9SAndroid Build Coastguard Worker 3018, /* dumpsys meminfo*/ }
56*d57664e9SAndroid Build Coastguard Worker
57*d57664e9SAndroid Build Coastguard Worker namespace android {
58*d57664e9SAndroid Build Coastguard Worker namespace os {
59*d57664e9SAndroid Build Coastguard Worker namespace incidentd {
60*d57664e9SAndroid Build Coastguard Worker
61*d57664e9SAndroid Build Coastguard Worker String16 const APPROVE_INCIDENT_REPORTS("android.permission.APPROVE_INCIDENT_REPORTS");
62*d57664e9SAndroid Build Coastguard Worker String16 const DUMP_PERMISSION("android.permission.DUMP");
63*d57664e9SAndroid Build Coastguard Worker String16 const USAGE_STATS_PERMISSION("android.permission.PACKAGE_USAGE_STATS");
64*d57664e9SAndroid Build Coastguard Worker
checkIncidentPermissions(const IncidentReportArgs & args)65*d57664e9SAndroid Build Coastguard Worker static Status checkIncidentPermissions(const IncidentReportArgs& args) {
66*d57664e9SAndroid Build Coastguard Worker uid_t callingUid = IPCThreadState::self()->getCallingUid();
67*d57664e9SAndroid Build Coastguard Worker pid_t callingPid = IPCThreadState::self()->getCallingPid();
68*d57664e9SAndroid Build Coastguard Worker if (callingUid == AID_ROOT || callingUid == AID_SHELL) {
69*d57664e9SAndroid Build Coastguard Worker // Root and shell are ok.
70*d57664e9SAndroid Build Coastguard Worker return Status::ok();
71*d57664e9SAndroid Build Coastguard Worker }
72*d57664e9SAndroid Build Coastguard Worker
73*d57664e9SAndroid Build Coastguard Worker if (checkCallingPermission(APPROVE_INCIDENT_REPORTS)) {
74*d57664e9SAndroid Build Coastguard Worker // Permission controller (this is a singleton permission that is always granted
75*d57664e9SAndroid Build Coastguard Worker // exactly for PermissionController) is allowed to access incident reports
76*d57664e9SAndroid Build Coastguard Worker // so it can show the user info about what they are approving.
77*d57664e9SAndroid Build Coastguard Worker return Status::ok();
78*d57664e9SAndroid Build Coastguard Worker }
79*d57664e9SAndroid Build Coastguard Worker
80*d57664e9SAndroid Build Coastguard Worker // checking calling permission.
81*d57664e9SAndroid Build Coastguard Worker if (!checkCallingPermission(DUMP_PERMISSION)) {
82*d57664e9SAndroid Build Coastguard Worker ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP",
83*d57664e9SAndroid Build Coastguard Worker callingPid, callingUid);
84*d57664e9SAndroid Build Coastguard Worker return Status::fromExceptionCode(
85*d57664e9SAndroid Build Coastguard Worker Status::EX_SECURITY,
86*d57664e9SAndroid Build Coastguard Worker "Calling process does not have permission: android.permission.DUMP");
87*d57664e9SAndroid Build Coastguard Worker }
88*d57664e9SAndroid Build Coastguard Worker if (!checkCallingPermission(USAGE_STATS_PERMISSION)) {
89*d57664e9SAndroid Build Coastguard Worker ALOGW("Calling pid %d and uid %d does not have permission: android.permission.USAGE_STATS",
90*d57664e9SAndroid Build Coastguard Worker callingPid, callingUid);
91*d57664e9SAndroid Build Coastguard Worker return Status::fromExceptionCode(
92*d57664e9SAndroid Build Coastguard Worker Status::EX_SECURITY,
93*d57664e9SAndroid Build Coastguard Worker "Calling process does not have permission: android.permission.USAGE_STATS");
94*d57664e9SAndroid Build Coastguard Worker }
95*d57664e9SAndroid Build Coastguard Worker
96*d57664e9SAndroid Build Coastguard Worker // checking calling request uid permission.
97*d57664e9SAndroid Build Coastguard Worker switch (args.getPrivacyPolicy()) {
98*d57664e9SAndroid Build Coastguard Worker case PRIVACY_POLICY_LOCAL:
99*d57664e9SAndroid Build Coastguard Worker if (callingUid != AID_SHELL && callingUid != AID_ROOT) {
100*d57664e9SAndroid Build Coastguard Worker ALOGW("Calling pid %d and uid %d does not have permission to get local data.",
101*d57664e9SAndroid Build Coastguard Worker callingPid, callingUid);
102*d57664e9SAndroid Build Coastguard Worker return Status::fromExceptionCode(
103*d57664e9SAndroid Build Coastguard Worker Status::EX_SECURITY,
104*d57664e9SAndroid Build Coastguard Worker "Calling process does not have permission to get local data.");
105*d57664e9SAndroid Build Coastguard Worker }
106*d57664e9SAndroid Build Coastguard Worker break;
107*d57664e9SAndroid Build Coastguard Worker case PRIVACY_POLICY_EXPLICIT:
108*d57664e9SAndroid Build Coastguard Worker if (callingUid != AID_SHELL && callingUid != AID_ROOT && callingUid != AID_STATSD &&
109*d57664e9SAndroid Build Coastguard Worker callingUid != AID_SYSTEM) {
110*d57664e9SAndroid Build Coastguard Worker ALOGW("Calling pid %d and uid %d does not have permission to get explicit data.",
111*d57664e9SAndroid Build Coastguard Worker callingPid, callingUid);
112*d57664e9SAndroid Build Coastguard Worker return Status::fromExceptionCode(
113*d57664e9SAndroid Build Coastguard Worker Status::EX_SECURITY,
114*d57664e9SAndroid Build Coastguard Worker "Calling process does not have permission to get explicit data.");
115*d57664e9SAndroid Build Coastguard Worker }
116*d57664e9SAndroid Build Coastguard Worker break;
117*d57664e9SAndroid Build Coastguard Worker }
118*d57664e9SAndroid Build Coastguard Worker return Status::ok();
119*d57664e9SAndroid Build Coastguard Worker }
120*d57664e9SAndroid Build Coastguard Worker
build_uri(const string & pkg,const string & cls,const string & id)121*d57664e9SAndroid Build Coastguard Worker static string build_uri(const string& pkg, const string& cls, const string& id) {
122*d57664e9SAndroid Build Coastguard Worker return "content://android.os.IncidentManager/pending?pkg="
123*d57664e9SAndroid Build Coastguard Worker + pkg + "&receiver=" + cls + "&r=" + id;
124*d57664e9SAndroid Build Coastguard Worker }
125*d57664e9SAndroid Build Coastguard Worker
126*d57664e9SAndroid Build Coastguard Worker // ================================================================================
ReportHandler(const sp<WorkDirectory> & workDirectory,const sp<Broadcaster> & broadcaster,const sp<Looper> & handlerLooper,const sp<Throttler> & throttler,const vector<BringYourOwnSection * > & registeredSections)127*d57664e9SAndroid Build Coastguard Worker ReportHandler::ReportHandler(const sp<WorkDirectory>& workDirectory,
128*d57664e9SAndroid Build Coastguard Worker const sp<Broadcaster>& broadcaster,
129*d57664e9SAndroid Build Coastguard Worker const sp<Looper>& handlerLooper,
130*d57664e9SAndroid Build Coastguard Worker const sp<Throttler>& throttler,
131*d57664e9SAndroid Build Coastguard Worker const vector<BringYourOwnSection*>& registeredSections)
132*d57664e9SAndroid Build Coastguard Worker :mLock(),
133*d57664e9SAndroid Build Coastguard Worker mWorkDirectory(workDirectory),
134*d57664e9SAndroid Build Coastguard Worker mBroadcaster(broadcaster),
135*d57664e9SAndroid Build Coastguard Worker mHandlerLooper(handlerLooper),
136*d57664e9SAndroid Build Coastguard Worker mBacklogDelay(DEFAULT_DELAY_NS),
137*d57664e9SAndroid Build Coastguard Worker mThrottler(throttler),
138*d57664e9SAndroid Build Coastguard Worker mRegisteredSections(registeredSections),
139*d57664e9SAndroid Build Coastguard Worker mBatch(new ReportBatch()) {
140*d57664e9SAndroid Build Coastguard Worker }
141*d57664e9SAndroid Build Coastguard Worker
~ReportHandler()142*d57664e9SAndroid Build Coastguard Worker ReportHandler::~ReportHandler() {
143*d57664e9SAndroid Build Coastguard Worker }
144*d57664e9SAndroid Build Coastguard Worker
handleMessage(const Message & message)145*d57664e9SAndroid Build Coastguard Worker void ReportHandler::handleMessage(const Message& message) {
146*d57664e9SAndroid Build Coastguard Worker switch (message.what) {
147*d57664e9SAndroid Build Coastguard Worker case WHAT_TAKE_REPORT:
148*d57664e9SAndroid Build Coastguard Worker take_report();
149*d57664e9SAndroid Build Coastguard Worker break;
150*d57664e9SAndroid Build Coastguard Worker case WHAT_SEND_BROADCASTS:
151*d57664e9SAndroid Build Coastguard Worker send_broadcasts();
152*d57664e9SAndroid Build Coastguard Worker break;
153*d57664e9SAndroid Build Coastguard Worker }
154*d57664e9SAndroid Build Coastguard Worker }
155*d57664e9SAndroid Build Coastguard Worker
schedulePersistedReport(const IncidentReportArgs & args)156*d57664e9SAndroid Build Coastguard Worker void ReportHandler::schedulePersistedReport(const IncidentReportArgs& args) {
157*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
158*d57664e9SAndroid Build Coastguard Worker mBatch->addPersistedReport(args);
159*d57664e9SAndroid Build Coastguard Worker mHandlerLooper->removeMessages(this, WHAT_TAKE_REPORT);
160*d57664e9SAndroid Build Coastguard Worker mHandlerLooper->sendMessage(this, Message(WHAT_TAKE_REPORT));
161*d57664e9SAndroid Build Coastguard Worker }
162*d57664e9SAndroid Build Coastguard Worker
scheduleStreamingReport(const IncidentReportArgs & args,const sp<IIncidentReportStatusListener> & listener,int streamFd)163*d57664e9SAndroid Build Coastguard Worker void ReportHandler::scheduleStreamingReport(const IncidentReportArgs& args,
164*d57664e9SAndroid Build Coastguard Worker const sp<IIncidentReportStatusListener>& listener, int streamFd) {
165*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
166*d57664e9SAndroid Build Coastguard Worker mBatch->addStreamingReport(args, listener, streamFd);
167*d57664e9SAndroid Build Coastguard Worker mHandlerLooper->removeMessages(this, WHAT_TAKE_REPORT);
168*d57664e9SAndroid Build Coastguard Worker mHandlerLooper->sendMessage(this, Message(WHAT_TAKE_REPORT));
169*d57664e9SAndroid Build Coastguard Worker }
170*d57664e9SAndroid Build Coastguard Worker
scheduleSendBacklog()171*d57664e9SAndroid Build Coastguard Worker void ReportHandler::scheduleSendBacklog() {
172*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
173*d57664e9SAndroid Build Coastguard Worker mBacklogDelay = DEFAULT_DELAY_NS;
174*d57664e9SAndroid Build Coastguard Worker schedule_send_broadcasts_locked();
175*d57664e9SAndroid Build Coastguard Worker }
176*d57664e9SAndroid Build Coastguard Worker
schedule_send_broadcasts_locked()177*d57664e9SAndroid Build Coastguard Worker void ReportHandler::schedule_send_broadcasts_locked() {
178*d57664e9SAndroid Build Coastguard Worker mHandlerLooper->removeMessages(this, WHAT_SEND_BROADCASTS);
179*d57664e9SAndroid Build Coastguard Worker mHandlerLooper->sendMessageDelayed(mBacklogDelay, this, Message(WHAT_SEND_BROADCASTS));
180*d57664e9SAndroid Build Coastguard Worker }
181*d57664e9SAndroid Build Coastguard Worker
take_report()182*d57664e9SAndroid Build Coastguard Worker void ReportHandler::take_report() {
183*d57664e9SAndroid Build Coastguard Worker // Cycle the batch and throttle.
184*d57664e9SAndroid Build Coastguard Worker sp<ReportBatch> batch;
185*d57664e9SAndroid Build Coastguard Worker {
186*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
187*d57664e9SAndroid Build Coastguard Worker batch = mThrottler->filterBatch(mBatch);
188*d57664e9SAndroid Build Coastguard Worker }
189*d57664e9SAndroid Build Coastguard Worker
190*d57664e9SAndroid Build Coastguard Worker if (batch->empty()) {
191*d57664e9SAndroid Build Coastguard Worker // Nothing to do.
192*d57664e9SAndroid Build Coastguard Worker return;
193*d57664e9SAndroid Build Coastguard Worker }
194*d57664e9SAndroid Build Coastguard Worker
195*d57664e9SAndroid Build Coastguard Worker sp<Reporter> reporter = new Reporter(mWorkDirectory, batch, mRegisteredSections);
196*d57664e9SAndroid Build Coastguard Worker
197*d57664e9SAndroid Build Coastguard Worker // Take the report, which might take a while. More requests might queue
198*d57664e9SAndroid Build Coastguard Worker // up while we're doing this, and we'll handle them in their next batch.
199*d57664e9SAndroid Build Coastguard Worker // TODO: We should further rate-limit the reports to no more than N per time-period.
200*d57664e9SAndroid Build Coastguard Worker // TODO: Move this inside reporter.
201*d57664e9SAndroid Build Coastguard Worker size_t reportByteSize = 0;
202*d57664e9SAndroid Build Coastguard Worker reporter->runReport(&reportByteSize);
203*d57664e9SAndroid Build Coastguard Worker
204*d57664e9SAndroid Build Coastguard Worker // Tell the throttler how big it was, for the next throttling.
205*d57664e9SAndroid Build Coastguard Worker // TODO: This still isn't ideal. The throttler really should just track the
206*d57664e9SAndroid Build Coastguard Worker // persisted reqeusts, but changing Reporter::runReport() to track that individually
207*d57664e9SAndroid Build Coastguard Worker // will be a big change.
208*d57664e9SAndroid Build Coastguard Worker if (batch->hasPersistedReports()) {
209*d57664e9SAndroid Build Coastguard Worker mThrottler->addReportSize(reportByteSize);
210*d57664e9SAndroid Build Coastguard Worker }
211*d57664e9SAndroid Build Coastguard Worker
212*d57664e9SAndroid Build Coastguard Worker // Kick off the next steps, one of which is to send any new or otherwise remaining
213*d57664e9SAndroid Build Coastguard Worker // approvals, and one of which is to send any new or remaining broadcasts.
214*d57664e9SAndroid Build Coastguard Worker {
215*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
216*d57664e9SAndroid Build Coastguard Worker schedule_send_broadcasts_locked();
217*d57664e9SAndroid Build Coastguard Worker }
218*d57664e9SAndroid Build Coastguard Worker }
219*d57664e9SAndroid Build Coastguard Worker
send_broadcasts()220*d57664e9SAndroid Build Coastguard Worker void ReportHandler::send_broadcasts() {
221*d57664e9SAndroid Build Coastguard Worker Broadcaster::broadcast_status_t result = mBroadcaster->sendBroadcasts();
222*d57664e9SAndroid Build Coastguard Worker if (result == Broadcaster::BROADCASTS_FINISHED) {
223*d57664e9SAndroid Build Coastguard Worker // We're done.
224*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
225*d57664e9SAndroid Build Coastguard Worker mBacklogDelay = DEFAULT_DELAY_NS;
226*d57664e9SAndroid Build Coastguard Worker } else if (result == Broadcaster::BROADCASTS_REPEAT) {
227*d57664e9SAndroid Build Coastguard Worker // It worked, but there are more.
228*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
229*d57664e9SAndroid Build Coastguard Worker mBacklogDelay = DEFAULT_DELAY_NS;
230*d57664e9SAndroid Build Coastguard Worker schedule_send_broadcasts_locked();
231*d57664e9SAndroid Build Coastguard Worker } else if (result == Broadcaster::BROADCASTS_BACKOFF) {
232*d57664e9SAndroid Build Coastguard Worker // There was a failure. Exponential backoff.
233*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
234*d57664e9SAndroid Build Coastguard Worker mBacklogDelay *= 2;
235*d57664e9SAndroid Build Coastguard Worker ALOGI("Error sending to dropbox. Trying again in %lld minutes",
236*d57664e9SAndroid Build Coastguard Worker (mBacklogDelay / (1000000000LL * 60)));
237*d57664e9SAndroid Build Coastguard Worker schedule_send_broadcasts_locked();
238*d57664e9SAndroid Build Coastguard Worker }
239*d57664e9SAndroid Build Coastguard Worker }
240*d57664e9SAndroid Build Coastguard Worker
241*d57664e9SAndroid Build Coastguard Worker // ================================================================================
IncidentService(const sp<Looper> & handlerLooper)242*d57664e9SAndroid Build Coastguard Worker IncidentService::IncidentService(const sp<Looper>& handlerLooper) {
243*d57664e9SAndroid Build Coastguard Worker mThrottler = new Throttler(DEFAULT_BYTES_SIZE_LIMIT, DEFAULT_REFACTORY_PERIOD_MS);
244*d57664e9SAndroid Build Coastguard Worker mWorkDirectory = new WorkDirectory();
245*d57664e9SAndroid Build Coastguard Worker mBroadcaster = new Broadcaster(mWorkDirectory);
246*d57664e9SAndroid Build Coastguard Worker mHandler = new ReportHandler(mWorkDirectory, mBroadcaster, handlerLooper,
247*d57664e9SAndroid Build Coastguard Worker mThrottler, mRegisteredSections);
248*d57664e9SAndroid Build Coastguard Worker mBroadcaster->setHandler(mHandler);
249*d57664e9SAndroid Build Coastguard Worker }
250*d57664e9SAndroid Build Coastguard Worker
~IncidentService()251*d57664e9SAndroid Build Coastguard Worker IncidentService::~IncidentService() {}
252*d57664e9SAndroid Build Coastguard Worker
reportIncident(const IncidentReportArgs & args)253*d57664e9SAndroid Build Coastguard Worker Status IncidentService::reportIncident(const IncidentReportArgs& args) {
254*d57664e9SAndroid Build Coastguard Worker IncidentReportArgs argsCopy(args);
255*d57664e9SAndroid Build Coastguard Worker
256*d57664e9SAndroid Build Coastguard Worker // Validate that the privacy policy is one of the real ones.
257*d57664e9SAndroid Build Coastguard Worker // If it isn't, clamp it to the next more restrictive real one.
258*d57664e9SAndroid Build Coastguard Worker argsCopy.setPrivacyPolicy(cleanup_privacy_policy(args.getPrivacyPolicy()));
259*d57664e9SAndroid Build Coastguard Worker
260*d57664e9SAndroid Build Coastguard Worker // TODO: Check that the broadcast recevier has the proper permissions
261*d57664e9SAndroid Build Coastguard Worker // TODO: Maybe we should consider relaxing the permissions if it's going to
262*d57664e9SAndroid Build Coastguard Worker // dropbox, but definitely not if it's going to the broadcaster.
263*d57664e9SAndroid Build Coastguard Worker Status status = checkIncidentPermissions(args);
264*d57664e9SAndroid Build Coastguard Worker if (!status.isOk()) {
265*d57664e9SAndroid Build Coastguard Worker return status;
266*d57664e9SAndroid Build Coastguard Worker }
267*d57664e9SAndroid Build Coastguard Worker
268*d57664e9SAndroid Build Coastguard Worker // If they asked for the LOCAL privacy policy, give them EXPLICT. LOCAL has to
269*d57664e9SAndroid Build Coastguard Worker // be streamed. (This only applies to shell/root, because everyone else would have
270*d57664e9SAndroid Build Coastguard Worker // been rejected by checkIncidentPermissions()).
271*d57664e9SAndroid Build Coastguard Worker if (argsCopy.getPrivacyPolicy() < PRIVACY_POLICY_EXPLICIT) {
272*d57664e9SAndroid Build Coastguard Worker ALOGI("Demoting privacy policy to EXPLICT for persisted report.");
273*d57664e9SAndroid Build Coastguard Worker argsCopy.setPrivacyPolicy(PRIVACY_POLICY_EXPLICIT);
274*d57664e9SAndroid Build Coastguard Worker }
275*d57664e9SAndroid Build Coastguard Worker
276*d57664e9SAndroid Build Coastguard Worker // If they didn't specify a component, use dropbox.
277*d57664e9SAndroid Build Coastguard Worker if (argsCopy.receiverPkg().length() == 0 && argsCopy.receiverCls().length() == 0) {
278*d57664e9SAndroid Build Coastguard Worker argsCopy.setReceiverPkg(DROPBOX_SENTINEL.getPackageName());
279*d57664e9SAndroid Build Coastguard Worker argsCopy.setReceiverCls(DROPBOX_SENTINEL.getClassName());
280*d57664e9SAndroid Build Coastguard Worker }
281*d57664e9SAndroid Build Coastguard Worker
282*d57664e9SAndroid Build Coastguard Worker mHandler->schedulePersistedReport(argsCopy);
283*d57664e9SAndroid Build Coastguard Worker
284*d57664e9SAndroid Build Coastguard Worker return Status::ok();
285*d57664e9SAndroid Build Coastguard Worker }
286*d57664e9SAndroid Build Coastguard Worker
reportIncidentToStream(const IncidentReportArgs & args,const sp<IIncidentReportStatusListener> & listener,unique_fd stream)287*d57664e9SAndroid Build Coastguard Worker Status IncidentService::reportIncidentToStream(const IncidentReportArgs& args,
288*d57664e9SAndroid Build Coastguard Worker const sp<IIncidentReportStatusListener>& listener,
289*d57664e9SAndroid Build Coastguard Worker unique_fd stream) {
290*d57664e9SAndroid Build Coastguard Worker IncidentReportArgs argsCopy(args);
291*d57664e9SAndroid Build Coastguard Worker
292*d57664e9SAndroid Build Coastguard Worker // Streaming reports can not also be broadcast.
293*d57664e9SAndroid Build Coastguard Worker argsCopy.setReceiverPkg("");
294*d57664e9SAndroid Build Coastguard Worker argsCopy.setReceiverCls("");
295*d57664e9SAndroid Build Coastguard Worker
296*d57664e9SAndroid Build Coastguard Worker // Validate that the privacy policy is one of the real ones.
297*d57664e9SAndroid Build Coastguard Worker // If it isn't, clamp it to the next more restrictive real one.
298*d57664e9SAndroid Build Coastguard Worker argsCopy.setPrivacyPolicy(cleanup_privacy_policy(args.getPrivacyPolicy()));
299*d57664e9SAndroid Build Coastguard Worker
300*d57664e9SAndroid Build Coastguard Worker Status status = checkIncidentPermissions(argsCopy);
301*d57664e9SAndroid Build Coastguard Worker if (!status.isOk()) {
302*d57664e9SAndroid Build Coastguard Worker return status;
303*d57664e9SAndroid Build Coastguard Worker }
304*d57664e9SAndroid Build Coastguard Worker
305*d57664e9SAndroid Build Coastguard Worker // The ReportRequest takes ownership of the fd, so we need to dup it.
306*d57664e9SAndroid Build Coastguard Worker int fd = dup(stream.get());
307*d57664e9SAndroid Build Coastguard Worker if (fd < 0) {
308*d57664e9SAndroid Build Coastguard Worker return Status::fromStatusT(-errno);
309*d57664e9SAndroid Build Coastguard Worker }
310*d57664e9SAndroid Build Coastguard Worker
311*d57664e9SAndroid Build Coastguard Worker mHandler->scheduleStreamingReport(argsCopy, listener, fd);
312*d57664e9SAndroid Build Coastguard Worker
313*d57664e9SAndroid Build Coastguard Worker return Status::ok();
314*d57664e9SAndroid Build Coastguard Worker }
315*d57664e9SAndroid Build Coastguard Worker
reportIncidentToDumpstate(unique_fd stream,const sp<IIncidentReportStatusListener> & listener)316*d57664e9SAndroid Build Coastguard Worker Status IncidentService::reportIncidentToDumpstate(unique_fd stream,
317*d57664e9SAndroid Build Coastguard Worker const sp<IIncidentReportStatusListener>& listener) {
318*d57664e9SAndroid Build Coastguard Worker uid_t caller = IPCThreadState::self()->getCallingUid();
319*d57664e9SAndroid Build Coastguard Worker if (caller != AID_ROOT && caller != AID_SHELL) {
320*d57664e9SAndroid Build Coastguard Worker ALOGW("Calling uid %d does not have permission: only ROOT or SHELL allowed", caller);
321*d57664e9SAndroid Build Coastguard Worker return Status::fromExceptionCode(Status::EX_SECURITY, "Only ROOT or SHELL allowed");
322*d57664e9SAndroid Build Coastguard Worker }
323*d57664e9SAndroid Build Coastguard Worker
324*d57664e9SAndroid Build Coastguard Worker ALOGD("Stream incident report to dumpstate");
325*d57664e9SAndroid Build Coastguard Worker IncidentReportArgs incidentArgs;
326*d57664e9SAndroid Build Coastguard Worker // Privacy policy for dumpstate incident reports is always EXPLICIT.
327*d57664e9SAndroid Build Coastguard Worker incidentArgs.setPrivacyPolicy(PRIVACY_POLICY_EXPLICIT);
328*d57664e9SAndroid Build Coastguard Worker
329*d57664e9SAndroid Build Coastguard Worker int skipped[] = SKIPPED_DUMPSTATE_SECTIONS;
330*d57664e9SAndroid Build Coastguard Worker for (const Section** section = SECTION_LIST; *section; section++) {
331*d57664e9SAndroid Build Coastguard Worker const int id = (*section)->id;
332*d57664e9SAndroid Build Coastguard Worker if (std::find(std::begin(skipped), std::end(skipped), id) == std::end(skipped)
333*d57664e9SAndroid Build Coastguard Worker && !section_requires_specific_mention(id)) {
334*d57664e9SAndroid Build Coastguard Worker incidentArgs.addSection(id);
335*d57664e9SAndroid Build Coastguard Worker }
336*d57664e9SAndroid Build Coastguard Worker }
337*d57664e9SAndroid Build Coastguard Worker for (const Section* section : mRegisteredSections) {
338*d57664e9SAndroid Build Coastguard Worker if (!section_requires_specific_mention(section->id)) {
339*d57664e9SAndroid Build Coastguard Worker incidentArgs.addSection(section->id);
340*d57664e9SAndroid Build Coastguard Worker }
341*d57664e9SAndroid Build Coastguard Worker }
342*d57664e9SAndroid Build Coastguard Worker
343*d57664e9SAndroid Build Coastguard Worker // The ReportRequest takes ownership of the fd, so we need to dup it.
344*d57664e9SAndroid Build Coastguard Worker int fd = dup(stream.get());
345*d57664e9SAndroid Build Coastguard Worker if (fd < 0) {
346*d57664e9SAndroid Build Coastguard Worker return Status::fromStatusT(-errno);
347*d57664e9SAndroid Build Coastguard Worker }
348*d57664e9SAndroid Build Coastguard Worker
349*d57664e9SAndroid Build Coastguard Worker mHandler->scheduleStreamingReport(incidentArgs, listener, fd);
350*d57664e9SAndroid Build Coastguard Worker
351*d57664e9SAndroid Build Coastguard Worker return Status::ok();
352*d57664e9SAndroid Build Coastguard Worker }
353*d57664e9SAndroid Build Coastguard Worker
registerSection(const int id,const String16 & name16,const sp<IIncidentDumpCallback> & callback)354*d57664e9SAndroid Build Coastguard Worker Status IncidentService::registerSection(const int id, const String16& name16,
355*d57664e9SAndroid Build Coastguard Worker const sp<IIncidentDumpCallback>& callback) {
356*d57664e9SAndroid Build Coastguard Worker const String8 name = String8(name16);
357*d57664e9SAndroid Build Coastguard Worker const uid_t callingUid = IPCThreadState::self()->getCallingUid();
358*d57664e9SAndroid Build Coastguard Worker ALOGI("Uid %d registers section %d '%s'", callingUid, id, name.c_str());
359*d57664e9SAndroid Build Coastguard Worker if (callback == nullptr) {
360*d57664e9SAndroid Build Coastguard Worker return Status::fromExceptionCode(Status::EX_NULL_POINTER);
361*d57664e9SAndroid Build Coastguard Worker }
362*d57664e9SAndroid Build Coastguard Worker for (int i = 0; i < mRegisteredSections.size(); i++) {
363*d57664e9SAndroid Build Coastguard Worker if (mRegisteredSections.at(i)->id == id) {
364*d57664e9SAndroid Build Coastguard Worker if (mRegisteredSections.at(i)->uid != callingUid) {
365*d57664e9SAndroid Build Coastguard Worker ALOGW("Error registering section %d: calling uid does not match", id);
366*d57664e9SAndroid Build Coastguard Worker return Status::fromExceptionCode(Status::EX_SECURITY);
367*d57664e9SAndroid Build Coastguard Worker }
368*d57664e9SAndroid Build Coastguard Worker mRegisteredSections.at(i) = new BringYourOwnSection(id, name.c_str(), callingUid, callback);
369*d57664e9SAndroid Build Coastguard Worker return Status::ok();
370*d57664e9SAndroid Build Coastguard Worker }
371*d57664e9SAndroid Build Coastguard Worker }
372*d57664e9SAndroid Build Coastguard Worker mRegisteredSections.push_back(new BringYourOwnSection(id, name.c_str(), callingUid, callback));
373*d57664e9SAndroid Build Coastguard Worker return Status::ok();
374*d57664e9SAndroid Build Coastguard Worker }
375*d57664e9SAndroid Build Coastguard Worker
unregisterSection(const int id)376*d57664e9SAndroid Build Coastguard Worker Status IncidentService::unregisterSection(const int id) {
377*d57664e9SAndroid Build Coastguard Worker uid_t callingUid = IPCThreadState::self()->getCallingUid();
378*d57664e9SAndroid Build Coastguard Worker ALOGI("Uid %d unregisters section %d", callingUid, id);
379*d57664e9SAndroid Build Coastguard Worker
380*d57664e9SAndroid Build Coastguard Worker for (auto it = mRegisteredSections.begin(); it != mRegisteredSections.end(); it++) {
381*d57664e9SAndroid Build Coastguard Worker if ((*it)->id == id) {
382*d57664e9SAndroid Build Coastguard Worker if ((*it)->uid != callingUid) {
383*d57664e9SAndroid Build Coastguard Worker ALOGW("Error unregistering section %d: calling uid does not match", id);
384*d57664e9SAndroid Build Coastguard Worker return Status::fromExceptionCode(Status::EX_SECURITY);
385*d57664e9SAndroid Build Coastguard Worker }
386*d57664e9SAndroid Build Coastguard Worker mRegisteredSections.erase(it);
387*d57664e9SAndroid Build Coastguard Worker return Status::ok();
388*d57664e9SAndroid Build Coastguard Worker }
389*d57664e9SAndroid Build Coastguard Worker }
390*d57664e9SAndroid Build Coastguard Worker ALOGW("Section %d not found", id);
391*d57664e9SAndroid Build Coastguard Worker return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
392*d57664e9SAndroid Build Coastguard Worker }
393*d57664e9SAndroid Build Coastguard Worker
systemRunning()394*d57664e9SAndroid Build Coastguard Worker Status IncidentService::systemRunning() {
395*d57664e9SAndroid Build Coastguard Worker if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
396*d57664e9SAndroid Build Coastguard Worker return Status::fromExceptionCode(Status::EX_SECURITY,
397*d57664e9SAndroid Build Coastguard Worker "Only system uid can call systemRunning");
398*d57664e9SAndroid Build Coastguard Worker }
399*d57664e9SAndroid Build Coastguard Worker
400*d57664e9SAndroid Build Coastguard Worker // When system_server is up and running, schedule the dropbox task to run.
401*d57664e9SAndroid Build Coastguard Worker mBroadcaster->reset();
402*d57664e9SAndroid Build Coastguard Worker mHandler->scheduleSendBacklog();
403*d57664e9SAndroid Build Coastguard Worker
404*d57664e9SAndroid Build Coastguard Worker return Status::ok();
405*d57664e9SAndroid Build Coastguard Worker }
406*d57664e9SAndroid Build Coastguard Worker
getIncidentReportList(const String16 & pkg16,const String16 & cls16,vector<String16> * result)407*d57664e9SAndroid Build Coastguard Worker Status IncidentService::getIncidentReportList(const String16& pkg16, const String16& cls16,
408*d57664e9SAndroid Build Coastguard Worker vector<String16>* result) {
409*d57664e9SAndroid Build Coastguard Worker status_t err;
410*d57664e9SAndroid Build Coastguard Worker const string pkg(String8(pkg16).c_str());
411*d57664e9SAndroid Build Coastguard Worker const string cls(String8(cls16).c_str());
412*d57664e9SAndroid Build Coastguard Worker
413*d57664e9SAndroid Build Coastguard Worker // List the reports
414*d57664e9SAndroid Build Coastguard Worker vector<sp<ReportFile>> all;
415*d57664e9SAndroid Build Coastguard Worker err = mWorkDirectory->getReports(&all, 0);
416*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
417*d57664e9SAndroid Build Coastguard Worker return Status::fromStatusT(err);
418*d57664e9SAndroid Build Coastguard Worker }
419*d57664e9SAndroid Build Coastguard Worker
420*d57664e9SAndroid Build Coastguard Worker // Find the ones that match pkg and cls.
421*d57664e9SAndroid Build Coastguard Worker for (sp<ReportFile>& file: all) {
422*d57664e9SAndroid Build Coastguard Worker err = file->loadEnvelope();
423*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
424*d57664e9SAndroid Build Coastguard Worker continue;
425*d57664e9SAndroid Build Coastguard Worker }
426*d57664e9SAndroid Build Coastguard Worker const ReportFileProto& envelope = file->getEnvelope();
427*d57664e9SAndroid Build Coastguard Worker size_t reportCount = envelope.report_size();
428*d57664e9SAndroid Build Coastguard Worker for (int reportIndex = 0; reportIndex < reportCount; reportIndex++) {
429*d57664e9SAndroid Build Coastguard Worker const ReportFileProto_Report& report = envelope.report(reportIndex);
430*d57664e9SAndroid Build Coastguard Worker if (pkg == report.pkg() && cls == report.cls()) {
431*d57664e9SAndroid Build Coastguard Worker result->push_back(String16(build_uri(pkg, cls, file->getId()).c_str()));
432*d57664e9SAndroid Build Coastguard Worker break;
433*d57664e9SAndroid Build Coastguard Worker }
434*d57664e9SAndroid Build Coastguard Worker }
435*d57664e9SAndroid Build Coastguard Worker }
436*d57664e9SAndroid Build Coastguard Worker
437*d57664e9SAndroid Build Coastguard Worker return Status::ok();
438*d57664e9SAndroid Build Coastguard Worker }
439*d57664e9SAndroid Build Coastguard Worker
getIncidentReport(const String16 & pkg16,const String16 & cls16,const String16 & id16,IncidentManager::IncidentReport * result)440*d57664e9SAndroid Build Coastguard Worker Status IncidentService::getIncidentReport(const String16& pkg16, const String16& cls16,
441*d57664e9SAndroid Build Coastguard Worker const String16& id16, IncidentManager::IncidentReport* result) {
442*d57664e9SAndroid Build Coastguard Worker status_t err;
443*d57664e9SAndroid Build Coastguard Worker
444*d57664e9SAndroid Build Coastguard Worker const string pkg(String8(pkg16).c_str());
445*d57664e9SAndroid Build Coastguard Worker const string cls(String8(cls16).c_str());
446*d57664e9SAndroid Build Coastguard Worker const string id(String8(id16).c_str());
447*d57664e9SAndroid Build Coastguard Worker
448*d57664e9SAndroid Build Coastguard Worker IncidentReportArgs args;
449*d57664e9SAndroid Build Coastguard Worker sp<ReportFile> file = mWorkDirectory->getReport(pkg, cls, id, &args);
450*d57664e9SAndroid Build Coastguard Worker if (file != nullptr) {
451*d57664e9SAndroid Build Coastguard Worker // Create pipe
452*d57664e9SAndroid Build Coastguard Worker int fds[2];
453*d57664e9SAndroid Build Coastguard Worker if (pipe(fds) != 0) {
454*d57664e9SAndroid Build Coastguard Worker ALOGW("Error opening pipe to filter incident report: %s",
455*d57664e9SAndroid Build Coastguard Worker file->getDataFileName().c_str());
456*d57664e9SAndroid Build Coastguard Worker return Status::ok();
457*d57664e9SAndroid Build Coastguard Worker }
458*d57664e9SAndroid Build Coastguard Worker result->setTimestampNs(file->getTimestampNs());
459*d57664e9SAndroid Build Coastguard Worker result->setPrivacyPolicy(file->getEnvelope().privacy_policy());
460*d57664e9SAndroid Build Coastguard Worker result->takeFileDescriptor(fds[0]);
461*d57664e9SAndroid Build Coastguard Worker int writeFd = fds[1];
462*d57664e9SAndroid Build Coastguard Worker // spawn a thread to write the data. Release the writeFd ownership to the thread.
463*d57664e9SAndroid Build Coastguard Worker thread th([file, writeFd, args]() { file->startFilteringData(writeFd, args); });
464*d57664e9SAndroid Build Coastguard Worker
465*d57664e9SAndroid Build Coastguard Worker th.detach();
466*d57664e9SAndroid Build Coastguard Worker }
467*d57664e9SAndroid Build Coastguard Worker
468*d57664e9SAndroid Build Coastguard Worker return Status::ok();
469*d57664e9SAndroid Build Coastguard Worker }
470*d57664e9SAndroid Build Coastguard Worker
deleteIncidentReports(const String16 & pkg16,const String16 & cls16,const String16 & id16)471*d57664e9SAndroid Build Coastguard Worker Status IncidentService::deleteIncidentReports(const String16& pkg16, const String16& cls16,
472*d57664e9SAndroid Build Coastguard Worker const String16& id16) {
473*d57664e9SAndroid Build Coastguard Worker const string pkg(String8(pkg16).c_str());
474*d57664e9SAndroid Build Coastguard Worker const string cls(String8(cls16).c_str());
475*d57664e9SAndroid Build Coastguard Worker const string id(String8(id16).c_str());
476*d57664e9SAndroid Build Coastguard Worker
477*d57664e9SAndroid Build Coastguard Worker sp<ReportFile> file = mWorkDirectory->getReport(pkg, cls, id, nullptr);
478*d57664e9SAndroid Build Coastguard Worker if (file != nullptr) {
479*d57664e9SAndroid Build Coastguard Worker mWorkDirectory->commit(file, pkg, cls);
480*d57664e9SAndroid Build Coastguard Worker }
481*d57664e9SAndroid Build Coastguard Worker mBroadcaster->clearBroadcasts(pkg, cls, id);
482*d57664e9SAndroid Build Coastguard Worker
483*d57664e9SAndroid Build Coastguard Worker return Status::ok();
484*d57664e9SAndroid Build Coastguard Worker }
485*d57664e9SAndroid Build Coastguard Worker
deleteAllIncidentReports(const String16 & pkg16)486*d57664e9SAndroid Build Coastguard Worker Status IncidentService::deleteAllIncidentReports(const String16& pkg16) {
487*d57664e9SAndroid Build Coastguard Worker const string pkg(String8(pkg16).c_str());
488*d57664e9SAndroid Build Coastguard Worker
489*d57664e9SAndroid Build Coastguard Worker mWorkDirectory->commitAll(pkg);
490*d57664e9SAndroid Build Coastguard Worker mBroadcaster->clearPackageBroadcasts(pkg);
491*d57664e9SAndroid Build Coastguard Worker
492*d57664e9SAndroid Build Coastguard Worker return Status::ok();
493*d57664e9SAndroid Build Coastguard Worker }
494*d57664e9SAndroid Build Coastguard Worker
495*d57664e9SAndroid Build Coastguard Worker /**
496*d57664e9SAndroid Build Coastguard Worker * Implement our own because the default binder implementation isn't
497*d57664e9SAndroid Build Coastguard Worker * properly handling SHELL_COMMAND_TRANSACTION.
498*d57664e9SAndroid Build Coastguard Worker */
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)499*d57664e9SAndroid Build Coastguard Worker status_t IncidentService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
500*d57664e9SAndroid Build Coastguard Worker uint32_t flags) {
501*d57664e9SAndroid Build Coastguard Worker status_t err;
502*d57664e9SAndroid Build Coastguard Worker
503*d57664e9SAndroid Build Coastguard Worker switch (code) {
504*d57664e9SAndroid Build Coastguard Worker case SHELL_COMMAND_TRANSACTION: {
505*d57664e9SAndroid Build Coastguard Worker unique_fd in, out, err;
506*d57664e9SAndroid Build Coastguard Worker if (status_t status = data.readUniqueFileDescriptor(&in); status != OK) return status;
507*d57664e9SAndroid Build Coastguard Worker
508*d57664e9SAndroid Build Coastguard Worker if (status_t status = data.readUniqueFileDescriptor(&out); status != OK) return status;
509*d57664e9SAndroid Build Coastguard Worker
510*d57664e9SAndroid Build Coastguard Worker if (status_t status = data.readUniqueFileDescriptor(&err); status != OK) return status;
511*d57664e9SAndroid Build Coastguard Worker
512*d57664e9SAndroid Build Coastguard Worker int argc = data.readInt32();
513*d57664e9SAndroid Build Coastguard Worker Vector<String8> args;
514*d57664e9SAndroid Build Coastguard Worker for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
515*d57664e9SAndroid Build Coastguard Worker args.add(String8(data.readString16()));
516*d57664e9SAndroid Build Coastguard Worker }
517*d57664e9SAndroid Build Coastguard Worker sp<IShellCallback> shellCallback = IShellCallback::asInterface(data.readStrongBinder());
518*d57664e9SAndroid Build Coastguard Worker sp<IResultReceiver> resultReceiver =
519*d57664e9SAndroid Build Coastguard Worker IResultReceiver::asInterface(data.readStrongBinder());
520*d57664e9SAndroid Build Coastguard Worker if (resultReceiver == nullptr) {
521*d57664e9SAndroid Build Coastguard Worker return BAD_VALUE;
522*d57664e9SAndroid Build Coastguard Worker }
523*d57664e9SAndroid Build Coastguard Worker
524*d57664e9SAndroid Build Coastguard Worker FILE* fin = fdopen(in.release(), "r");
525*d57664e9SAndroid Build Coastguard Worker FILE* fout = fdopen(out.release(), "w");
526*d57664e9SAndroid Build Coastguard Worker FILE* ferr = fdopen(err.release(), "w");
527*d57664e9SAndroid Build Coastguard Worker
528*d57664e9SAndroid Build Coastguard Worker if (fin == NULL || fout == NULL || ferr == NULL) {
529*d57664e9SAndroid Build Coastguard Worker resultReceiver->send(NO_MEMORY);
530*d57664e9SAndroid Build Coastguard Worker } else {
531*d57664e9SAndroid Build Coastguard Worker status_t result = command(fin, fout, ferr, args);
532*d57664e9SAndroid Build Coastguard Worker resultReceiver->send(result);
533*d57664e9SAndroid Build Coastguard Worker }
534*d57664e9SAndroid Build Coastguard Worker
535*d57664e9SAndroid Build Coastguard Worker if (fin != NULL) {
536*d57664e9SAndroid Build Coastguard Worker fflush(fin);
537*d57664e9SAndroid Build Coastguard Worker fclose(fin);
538*d57664e9SAndroid Build Coastguard Worker }
539*d57664e9SAndroid Build Coastguard Worker if (fout != NULL) {
540*d57664e9SAndroid Build Coastguard Worker fflush(fout);
541*d57664e9SAndroid Build Coastguard Worker fclose(fout);
542*d57664e9SAndroid Build Coastguard Worker }
543*d57664e9SAndroid Build Coastguard Worker if (ferr != NULL) {
544*d57664e9SAndroid Build Coastguard Worker fflush(ferr);
545*d57664e9SAndroid Build Coastguard Worker fclose(ferr);
546*d57664e9SAndroid Build Coastguard Worker }
547*d57664e9SAndroid Build Coastguard Worker
548*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
549*d57664e9SAndroid Build Coastguard Worker } break;
550*d57664e9SAndroid Build Coastguard Worker default: { return BnIncidentManager::onTransact(code, data, reply, flags); }
551*d57664e9SAndroid Build Coastguard Worker }
552*d57664e9SAndroid Build Coastguard Worker }
553*d57664e9SAndroid Build Coastguard Worker
command(FILE * in,FILE * out,FILE * err,Vector<String8> & args)554*d57664e9SAndroid Build Coastguard Worker status_t IncidentService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
555*d57664e9SAndroid Build Coastguard Worker const int argCount = args.size();
556*d57664e9SAndroid Build Coastguard Worker
557*d57664e9SAndroid Build Coastguard Worker if (argCount >= 1) {
558*d57664e9SAndroid Build Coastguard Worker if (!args[0].compare(String8("privacy"))) {
559*d57664e9SAndroid Build Coastguard Worker return cmd_privacy(in, out, err, args);
560*d57664e9SAndroid Build Coastguard Worker }
561*d57664e9SAndroid Build Coastguard Worker if (!args[0].compare(String8("throttler"))) {
562*d57664e9SAndroid Build Coastguard Worker mThrottler->dump(out);
563*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
564*d57664e9SAndroid Build Coastguard Worker }
565*d57664e9SAndroid Build Coastguard Worker if (!args[0].compare(String8("section"))) {
566*d57664e9SAndroid Build Coastguard Worker if (argCount == 1) {
567*d57664e9SAndroid Build Coastguard Worker fprintf(out, "Not enough arguments for section\n");
568*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
569*d57664e9SAndroid Build Coastguard Worker }
570*d57664e9SAndroid Build Coastguard Worker int id = atoi(args[1].c_str());
571*d57664e9SAndroid Build Coastguard Worker int idx = 0;
572*d57664e9SAndroid Build Coastguard Worker while (SECTION_LIST[idx] != NULL) {
573*d57664e9SAndroid Build Coastguard Worker const Section* section = SECTION_LIST[idx];
574*d57664e9SAndroid Build Coastguard Worker if (section->id == id) {
575*d57664e9SAndroid Build Coastguard Worker fprintf(out, "Section[%d] %s\n", id, section->name.c_str());
576*d57664e9SAndroid Build Coastguard Worker break;
577*d57664e9SAndroid Build Coastguard Worker }
578*d57664e9SAndroid Build Coastguard Worker idx++;
579*d57664e9SAndroid Build Coastguard Worker }
580*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
581*d57664e9SAndroid Build Coastguard Worker }
582*d57664e9SAndroid Build Coastguard Worker }
583*d57664e9SAndroid Build Coastguard Worker return cmd_help(out);
584*d57664e9SAndroid Build Coastguard Worker }
585*d57664e9SAndroid Build Coastguard Worker
cmd_help(FILE * out)586*d57664e9SAndroid Build Coastguard Worker status_t IncidentService::cmd_help(FILE* out) {
587*d57664e9SAndroid Build Coastguard Worker fprintf(out, "usage: adb shell cmd incident privacy print <section_id>\n");
588*d57664e9SAndroid Build Coastguard Worker fprintf(out, "usage: adb shell cmd incident privacy parse <section_id> < proto.txt\n");
589*d57664e9SAndroid Build Coastguard Worker fprintf(out, " Prints/parses for the section id.\n\n");
590*d57664e9SAndroid Build Coastguard Worker fprintf(out, "usage: adb shell cmd incident section <section_id>\n");
591*d57664e9SAndroid Build Coastguard Worker fprintf(out, " Prints section id and its name.\n\n");
592*d57664e9SAndroid Build Coastguard Worker fprintf(out, "usage: adb shell cmd incident throttler\n");
593*d57664e9SAndroid Build Coastguard Worker fprintf(out, " Prints the current throttler state\n");
594*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
595*d57664e9SAndroid Build Coastguard Worker }
596*d57664e9SAndroid Build Coastguard Worker
printPrivacy(const Privacy * p,FILE * out,String8 indent)597*d57664e9SAndroid Build Coastguard Worker static void printPrivacy(const Privacy* p, FILE* out, String8 indent) {
598*d57664e9SAndroid Build Coastguard Worker if (p == NULL) return;
599*d57664e9SAndroid Build Coastguard Worker fprintf(out, "%sid:%d, type:%d, dest:%d\n", indent.c_str(), p->field_id, p->type, p->policy);
600*d57664e9SAndroid Build Coastguard Worker if (p->children == NULL) return;
601*d57664e9SAndroid Build Coastguard Worker for (int i = 0; p->children[i] != NULL; i++) { // NULL-terminated.
602*d57664e9SAndroid Build Coastguard Worker printPrivacy(p->children[i], out, indent + " ");
603*d57664e9SAndroid Build Coastguard Worker }
604*d57664e9SAndroid Build Coastguard Worker }
605*d57664e9SAndroid Build Coastguard Worker
cmd_privacy(FILE * in,FILE * out,FILE * err,Vector<String8> & args)606*d57664e9SAndroid Build Coastguard Worker status_t IncidentService::cmd_privacy(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
607*d57664e9SAndroid Build Coastguard Worker (void)in;
608*d57664e9SAndroid Build Coastguard Worker
609*d57664e9SAndroid Build Coastguard Worker const int argCount = args.size();
610*d57664e9SAndroid Build Coastguard Worker if (argCount >= 3) {
611*d57664e9SAndroid Build Coastguard Worker String8 opt = args[1];
612*d57664e9SAndroid Build Coastguard Worker int sectionId = atoi(args[2].c_str());
613*d57664e9SAndroid Build Coastguard Worker
614*d57664e9SAndroid Build Coastguard Worker const Privacy* p = get_privacy_of_section(sectionId);
615*d57664e9SAndroid Build Coastguard Worker if (p == NULL) {
616*d57664e9SAndroid Build Coastguard Worker fprintf(err, "Can't find section id %d\n", sectionId);
617*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
618*d57664e9SAndroid Build Coastguard Worker }
619*d57664e9SAndroid Build Coastguard Worker fprintf(err, "Get privacy for %d\n", sectionId);
620*d57664e9SAndroid Build Coastguard Worker if (opt == "print") {
621*d57664e9SAndroid Build Coastguard Worker printPrivacy(p, out, String8(""));
622*d57664e9SAndroid Build Coastguard Worker } else if (opt == "parse") {
623*d57664e9SAndroid Build Coastguard Worker /*
624*d57664e9SAndroid Build Coastguard Worker FdBuffer buf;
625*d57664e9SAndroid Build Coastguard Worker status_t error = buf.read(fileno(in), 60000);
626*d57664e9SAndroid Build Coastguard Worker if (error != NO_ERROR) {
627*d57664e9SAndroid Build Coastguard Worker fprintf(err, "Error reading from stdin\n");
628*d57664e9SAndroid Build Coastguard Worker return error;
629*d57664e9SAndroid Build Coastguard Worker }
630*d57664e9SAndroid Build Coastguard Worker fprintf(err, "Read %zu bytes\n", buf.size());
631*d57664e9SAndroid Build Coastguard Worker PrivacyFilter pBuf(p, buf.data());
632*d57664e9SAndroid Build Coastguard Worker
633*d57664e9SAndroid Build Coastguard Worker PrivacySpec spec = PrivacySpec::new_spec(argCount > 3 ? atoi(args[3]) : -1);
634*d57664e9SAndroid Build Coastguard Worker error = pBuf.strip(spec);
635*d57664e9SAndroid Build Coastguard Worker if (error != NO_ERROR) {
636*d57664e9SAndroid Build Coastguard Worker fprintf(err, "Error strip pii fields with spec %d\n", spec.policy);
637*d57664e9SAndroid Build Coastguard Worker return error;
638*d57664e9SAndroid Build Coastguard Worker }
639*d57664e9SAndroid Build Coastguard Worker return pBuf.flush(fileno(out));
640*d57664e9SAndroid Build Coastguard Worker */
641*d57664e9SAndroid Build Coastguard Worker return -1;
642*d57664e9SAndroid Build Coastguard Worker }
643*d57664e9SAndroid Build Coastguard Worker } else {
644*d57664e9SAndroid Build Coastguard Worker return cmd_help(out);
645*d57664e9SAndroid Build Coastguard Worker }
646*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
647*d57664e9SAndroid Build Coastguard Worker }
648*d57664e9SAndroid Build Coastguard Worker
649*d57664e9SAndroid Build Coastguard Worker } // namespace incidentd
650*d57664e9SAndroid Build Coastguard Worker } // namespace os
651*d57664e9SAndroid Build Coastguard Worker } // namespace android
652