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
17*d57664e9SAndroid Build Coastguard Worker #include "Log.h"
18*d57664e9SAndroid Build Coastguard Worker
19*d57664e9SAndroid Build Coastguard Worker #include "Broadcaster.h"
20*d57664e9SAndroid Build Coastguard Worker
21*d57664e9SAndroid Build Coastguard Worker #include "IncidentService.h"
22*d57664e9SAndroid Build Coastguard Worker
23*d57664e9SAndroid Build Coastguard Worker #include <android/os/DropBoxManager.h>
24*d57664e9SAndroid Build Coastguard Worker #include <binder/IServiceManager.h>
25*d57664e9SAndroid Build Coastguard Worker #include <thread>
26*d57664e9SAndroid Build Coastguard Worker
27*d57664e9SAndroid Build Coastguard Worker namespace android {
28*d57664e9SAndroid Build Coastguard Worker namespace os {
29*d57664e9SAndroid Build Coastguard Worker namespace incidentd {
30*d57664e9SAndroid Build Coastguard Worker
31*d57664e9SAndroid Build Coastguard Worker using android::os::IIncidentCompanion;
32*d57664e9SAndroid Build Coastguard Worker using binder::Status;
33*d57664e9SAndroid Build Coastguard Worker
34*d57664e9SAndroid Build Coastguard Worker // ============================================================
ConsentListener(const sp<Broadcaster> & broadcaster,const ReportId & reportId)35*d57664e9SAndroid Build Coastguard Worker Broadcaster::ConsentListener::ConsentListener(const sp<Broadcaster>& broadcaster,
36*d57664e9SAndroid Build Coastguard Worker const ReportId& reportId)
37*d57664e9SAndroid Build Coastguard Worker :mBroadcaster(broadcaster),
38*d57664e9SAndroid Build Coastguard Worker mId(reportId) {
39*d57664e9SAndroid Build Coastguard Worker }
40*d57664e9SAndroid Build Coastguard Worker
~ConsentListener()41*d57664e9SAndroid Build Coastguard Worker Broadcaster::ConsentListener::~ConsentListener() {
42*d57664e9SAndroid Build Coastguard Worker }
43*d57664e9SAndroid Build Coastguard Worker
onReportApproved()44*d57664e9SAndroid Build Coastguard Worker Status Broadcaster::ConsentListener::onReportApproved() {
45*d57664e9SAndroid Build Coastguard Worker mBroadcaster->report_approved(mId);
46*d57664e9SAndroid Build Coastguard Worker return Status::ok();
47*d57664e9SAndroid Build Coastguard Worker }
48*d57664e9SAndroid Build Coastguard Worker
onReportDenied()49*d57664e9SAndroid Build Coastguard Worker Status Broadcaster::ConsentListener::onReportDenied() {
50*d57664e9SAndroid Build Coastguard Worker mBroadcaster->report_denied(mId);
51*d57664e9SAndroid Build Coastguard Worker return Status::ok();
52*d57664e9SAndroid Build Coastguard Worker }
53*d57664e9SAndroid Build Coastguard Worker
54*d57664e9SAndroid Build Coastguard Worker // ============================================================
ReportId()55*d57664e9SAndroid Build Coastguard Worker Broadcaster::ReportId::ReportId()
56*d57664e9SAndroid Build Coastguard Worker :id(),
57*d57664e9SAndroid Build Coastguard Worker pkg(),
58*d57664e9SAndroid Build Coastguard Worker cls() {
59*d57664e9SAndroid Build Coastguard Worker }
60*d57664e9SAndroid Build Coastguard Worker
ReportId(const ReportId & that)61*d57664e9SAndroid Build Coastguard Worker Broadcaster::ReportId::ReportId(const ReportId& that)
62*d57664e9SAndroid Build Coastguard Worker :id(that.id),
63*d57664e9SAndroid Build Coastguard Worker pkg(that.pkg),
64*d57664e9SAndroid Build Coastguard Worker cls(that.cls) {
65*d57664e9SAndroid Build Coastguard Worker }
66*d57664e9SAndroid Build Coastguard Worker
ReportId(const string & i,const string & p,const string & c)67*d57664e9SAndroid Build Coastguard Worker Broadcaster::ReportId::ReportId(const string& i, const string& p, const string& c)
68*d57664e9SAndroid Build Coastguard Worker :id(i),
69*d57664e9SAndroid Build Coastguard Worker pkg(p),
70*d57664e9SAndroid Build Coastguard Worker cls(c) {
71*d57664e9SAndroid Build Coastguard Worker }
72*d57664e9SAndroid Build Coastguard Worker
~ReportId()73*d57664e9SAndroid Build Coastguard Worker Broadcaster::ReportId::~ReportId() {
74*d57664e9SAndroid Build Coastguard Worker }
75*d57664e9SAndroid Build Coastguard Worker
operator <(const ReportId & that) const76*d57664e9SAndroid Build Coastguard Worker bool Broadcaster::ReportId::operator<(const ReportId& that) const {
77*d57664e9SAndroid Build Coastguard Worker if (id < that.id) {
78*d57664e9SAndroid Build Coastguard Worker return true;
79*d57664e9SAndroid Build Coastguard Worker }
80*d57664e9SAndroid Build Coastguard Worker if (id > that.id) {
81*d57664e9SAndroid Build Coastguard Worker return false;
82*d57664e9SAndroid Build Coastguard Worker }
83*d57664e9SAndroid Build Coastguard Worker if (pkg < that.pkg) {
84*d57664e9SAndroid Build Coastguard Worker return true;
85*d57664e9SAndroid Build Coastguard Worker }
86*d57664e9SAndroid Build Coastguard Worker if (pkg > that.pkg) {
87*d57664e9SAndroid Build Coastguard Worker return false;
88*d57664e9SAndroid Build Coastguard Worker }
89*d57664e9SAndroid Build Coastguard Worker if (cls < that.cls) {
90*d57664e9SAndroid Build Coastguard Worker return true;
91*d57664e9SAndroid Build Coastguard Worker }
92*d57664e9SAndroid Build Coastguard Worker return false;
93*d57664e9SAndroid Build Coastguard Worker }
94*d57664e9SAndroid Build Coastguard Worker
95*d57664e9SAndroid Build Coastguard Worker // ============================================================
ReportStatus()96*d57664e9SAndroid Build Coastguard Worker Broadcaster::ReportStatus::ReportStatus()
97*d57664e9SAndroid Build Coastguard Worker :approval_sent(false),
98*d57664e9SAndroid Build Coastguard Worker ready_sent(false),
99*d57664e9SAndroid Build Coastguard Worker listener(nullptr) {
100*d57664e9SAndroid Build Coastguard Worker }
101*d57664e9SAndroid Build Coastguard Worker
ReportStatus(const ReportStatus & that)102*d57664e9SAndroid Build Coastguard Worker Broadcaster::ReportStatus::ReportStatus(const ReportStatus& that)
103*d57664e9SAndroid Build Coastguard Worker :approval_sent(that.approval_sent),
104*d57664e9SAndroid Build Coastguard Worker ready_sent(that.ready_sent),
105*d57664e9SAndroid Build Coastguard Worker listener(that.listener) {
106*d57664e9SAndroid Build Coastguard Worker }
107*d57664e9SAndroid Build Coastguard Worker
~ReportStatus()108*d57664e9SAndroid Build Coastguard Worker Broadcaster::ReportStatus::~ReportStatus() {
109*d57664e9SAndroid Build Coastguard Worker }
110*d57664e9SAndroid Build Coastguard Worker
111*d57664e9SAndroid Build Coastguard Worker // ============================================================
Broadcaster(const sp<WorkDirectory> & workDirectory)112*d57664e9SAndroid Build Coastguard Worker Broadcaster::Broadcaster(const sp<WorkDirectory>& workDirectory)
113*d57664e9SAndroid Build Coastguard Worker :mReportHandler(),
114*d57664e9SAndroid Build Coastguard Worker mWorkDirectory(workDirectory) {
115*d57664e9SAndroid Build Coastguard Worker }
116*d57664e9SAndroid Build Coastguard Worker
setHandler(const sp<ReportHandler> & handler)117*d57664e9SAndroid Build Coastguard Worker void Broadcaster::setHandler(const sp<ReportHandler>& handler) {
118*d57664e9SAndroid Build Coastguard Worker mReportHandler = handler;
119*d57664e9SAndroid Build Coastguard Worker }
120*d57664e9SAndroid Build Coastguard Worker
reset()121*d57664e9SAndroid Build Coastguard Worker void Broadcaster::reset() {
122*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
123*d57664e9SAndroid Build Coastguard Worker mLastSent = 0;
124*d57664e9SAndroid Build Coastguard Worker mHistory.clear();
125*d57664e9SAndroid Build Coastguard Worker // Could cancel the listeners, but this happens when
126*d57664e9SAndroid Build Coastguard Worker // the system process crashes, so don't bother.
127*d57664e9SAndroid Build Coastguard Worker }
128*d57664e9SAndroid Build Coastguard Worker
clearBroadcasts(const string & pkg,const string & cls,const string & id)129*d57664e9SAndroid Build Coastguard Worker void Broadcaster::clearBroadcasts(const string& pkg, const string& cls, const string& id) {
130*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
131*d57664e9SAndroid Build Coastguard Worker
132*d57664e9SAndroid Build Coastguard Worker map<ReportId,ReportStatus>::const_iterator found = mHistory.find(ReportId(id, pkg, cls));
133*d57664e9SAndroid Build Coastguard Worker if (found != mHistory.end()) {
134*d57664e9SAndroid Build Coastguard Worker if (found->second.listener != nullptr) {
135*d57664e9SAndroid Build Coastguard Worker sp<IIncidentCompanion> ics = get_incident_companion();
136*d57664e9SAndroid Build Coastguard Worker if (ics != nullptr) {
137*d57664e9SAndroid Build Coastguard Worker ics->cancelAuthorization(found->second.listener);
138*d57664e9SAndroid Build Coastguard Worker }
139*d57664e9SAndroid Build Coastguard Worker }
140*d57664e9SAndroid Build Coastguard Worker mHistory.erase(found);
141*d57664e9SAndroid Build Coastguard Worker }
142*d57664e9SAndroid Build Coastguard Worker }
143*d57664e9SAndroid Build Coastguard Worker
clearPackageBroadcasts(const string & pkg)144*d57664e9SAndroid Build Coastguard Worker void Broadcaster::clearPackageBroadcasts(const string& pkg) {
145*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
146*d57664e9SAndroid Build Coastguard Worker
147*d57664e9SAndroid Build Coastguard Worker map<ReportId,ReportStatus>::iterator it = mHistory.begin();
148*d57664e9SAndroid Build Coastguard Worker while (it != mHistory.end()) {
149*d57664e9SAndroid Build Coastguard Worker if (it->first.pkg == pkg) {
150*d57664e9SAndroid Build Coastguard Worker if (it->second.listener != nullptr) {
151*d57664e9SAndroid Build Coastguard Worker sp<IIncidentCompanion> ics = get_incident_companion();
152*d57664e9SAndroid Build Coastguard Worker if (ics != nullptr) {
153*d57664e9SAndroid Build Coastguard Worker ics->cancelAuthorization(it->second.listener);
154*d57664e9SAndroid Build Coastguard Worker }
155*d57664e9SAndroid Build Coastguard Worker }
156*d57664e9SAndroid Build Coastguard Worker it = mHistory.erase(it);
157*d57664e9SAndroid Build Coastguard Worker } else {
158*d57664e9SAndroid Build Coastguard Worker it++;
159*d57664e9SAndroid Build Coastguard Worker }
160*d57664e9SAndroid Build Coastguard Worker }
161*d57664e9SAndroid Build Coastguard Worker }
162*d57664e9SAndroid Build Coastguard Worker
sendBroadcasts()163*d57664e9SAndroid Build Coastguard Worker Broadcaster::broadcast_status_t Broadcaster::sendBroadcasts() {
164*d57664e9SAndroid Build Coastguard Worker int err;
165*d57664e9SAndroid Build Coastguard Worker int64_t lastSent = get_last_sent();
166*d57664e9SAndroid Build Coastguard Worker
167*d57664e9SAndroid Build Coastguard Worker vector<sp<ReportFile>> files;
168*d57664e9SAndroid Build Coastguard Worker mWorkDirectory->getReports(&files, 0); //lastSent);
169*d57664e9SAndroid Build Coastguard Worker
170*d57664e9SAndroid Build Coastguard Worker // Don't send multiple broadcasts to the same receiver.
171*d57664e9SAndroid Build Coastguard Worker set<ReportId> reportReadyBroadcasts;
172*d57664e9SAndroid Build Coastguard Worker
173*d57664e9SAndroid Build Coastguard Worker for (const sp<ReportFile>& file: files) {
174*d57664e9SAndroid Build Coastguard Worker err = file->loadEnvelope();
175*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
176*d57664e9SAndroid Build Coastguard Worker ALOGW("Error (%s) loading envelope from %s", strerror(-err),
177*d57664e9SAndroid Build Coastguard Worker file->getEnvelopeFileName().c_str());
178*d57664e9SAndroid Build Coastguard Worker continue;
179*d57664e9SAndroid Build Coastguard Worker }
180*d57664e9SAndroid Build Coastguard Worker
181*d57664e9SAndroid Build Coastguard Worker const ReportFileProto& envelope = file->getEnvelope();
182*d57664e9SAndroid Build Coastguard Worker
183*d57664e9SAndroid Build Coastguard Worker if (!envelope.completed()) {
184*d57664e9SAndroid Build Coastguard Worker ALOGI("Incident report not completed skipping it: %s",
185*d57664e9SAndroid Build Coastguard Worker file->getEnvelopeFileName().c_str());
186*d57664e9SAndroid Build Coastguard Worker continue;
187*d57664e9SAndroid Build Coastguard Worker }
188*d57664e9SAndroid Build Coastguard Worker
189*d57664e9SAndroid Build Coastguard Worker // When one of the broadcast functions in this loop fails, it's almost
190*d57664e9SAndroid Build Coastguard Worker // certainly because the system process is crashing or has crashed. Rather
191*d57664e9SAndroid Build Coastguard Worker // than continuing to pound on the system process and potentially make things
192*d57664e9SAndroid Build Coastguard Worker // worse, we bail right away, return BROADCASTS_BACKOFF, and we will try
193*d57664e9SAndroid Build Coastguard Worker // again later. In the meantime, if the system process did crash, it might
194*d57664e9SAndroid Build Coastguard Worker // clear out mHistory, which means we'll be back here again to send the
195*d57664e9SAndroid Build Coastguard Worker // backlog.
196*d57664e9SAndroid Build Coastguard Worker size_t reportCount = envelope.report_size();
197*d57664e9SAndroid Build Coastguard Worker bool hasApprovalPending = false;
198*d57664e9SAndroid Build Coastguard Worker for (int reportIndex = 0; reportIndex < reportCount; reportIndex++) {
199*d57664e9SAndroid Build Coastguard Worker
200*d57664e9SAndroid Build Coastguard Worker const ReportFileProto_Report& report = envelope.report(reportIndex);
201*d57664e9SAndroid Build Coastguard Worker status_t err;
202*d57664e9SAndroid Build Coastguard Worker if (report.privacy_policy() == PRIVACY_POLICY_AUTOMATIC || report.share_approved()) {
203*d57664e9SAndroid Build Coastguard Worker // It's privacy policy is AUTO, or it's been approved,
204*d57664e9SAndroid Build Coastguard Worker // so send the actual broadcast.
205*d57664e9SAndroid Build Coastguard Worker if (!was_ready_sent(file->getId(), report.pkg(), report.cls())) {
206*d57664e9SAndroid Build Coastguard Worker if (report.pkg() == DROPBOX_SENTINEL.getPackageName()
207*d57664e9SAndroid Build Coastguard Worker && report.cls() == DROPBOX_SENTINEL.getClassName()) {
208*d57664e9SAndroid Build Coastguard Worker IncidentReportArgs args;
209*d57664e9SAndroid Build Coastguard Worker get_args_from_report(&args, report);
210*d57664e9SAndroid Build Coastguard Worker err = send_to_dropbox(file, args);
211*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
212*d57664e9SAndroid Build Coastguard Worker return BROADCASTS_BACKOFF;
213*d57664e9SAndroid Build Coastguard Worker }
214*d57664e9SAndroid Build Coastguard Worker } else {
215*d57664e9SAndroid Build Coastguard Worker reportReadyBroadcasts.insert(ReportId(file->getId(), report.pkg(),
216*d57664e9SAndroid Build Coastguard Worker report.cls()));
217*d57664e9SAndroid Build Coastguard Worker }
218*d57664e9SAndroid Build Coastguard Worker }
219*d57664e9SAndroid Build Coastguard Worker } else {
220*d57664e9SAndroid Build Coastguard Worker // It's not approved yet, so send the approval.
221*d57664e9SAndroid Build Coastguard Worker if (!was_approval_sent(file->getId(), report.pkg(), report.cls())) {
222*d57664e9SAndroid Build Coastguard Worker err = send_approval_broadcasts(file->getId(), report.pkg(), report.cls());
223*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
224*d57664e9SAndroid Build Coastguard Worker return BROADCASTS_BACKOFF;
225*d57664e9SAndroid Build Coastguard Worker }
226*d57664e9SAndroid Build Coastguard Worker hasApprovalPending = true;
227*d57664e9SAndroid Build Coastguard Worker }
228*d57664e9SAndroid Build Coastguard Worker }
229*d57664e9SAndroid Build Coastguard Worker }
230*d57664e9SAndroid Build Coastguard Worker
231*d57664e9SAndroid Build Coastguard Worker lastSent = file->getTimestampNs();
232*d57664e9SAndroid Build Coastguard Worker if (!hasApprovalPending) {
233*d57664e9SAndroid Build Coastguard Worker set_last_sent(lastSent);
234*d57664e9SAndroid Build Coastguard Worker }
235*d57664e9SAndroid Build Coastguard Worker }
236*d57664e9SAndroid Build Coastguard Worker
237*d57664e9SAndroid Build Coastguard Worker for (const ReportId& report: reportReadyBroadcasts) {
238*d57664e9SAndroid Build Coastguard Worker err = send_report_ready_broadcasts(report.id, report.pkg, report.cls);
239*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
240*d57664e9SAndroid Build Coastguard Worker return BROADCASTS_BACKOFF;
241*d57664e9SAndroid Build Coastguard Worker }
242*d57664e9SAndroid Build Coastguard Worker }
243*d57664e9SAndroid Build Coastguard Worker
244*d57664e9SAndroid Build Coastguard Worker return mWorkDirectory->hasMore(lastSent) ? BROADCASTS_REPEAT : BROADCASTS_FINISHED;
245*d57664e9SAndroid Build Coastguard Worker }
246*d57664e9SAndroid Build Coastguard Worker
set_last_sent(int64_t timestamp)247*d57664e9SAndroid Build Coastguard Worker void Broadcaster::set_last_sent(int64_t timestamp) {
248*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
249*d57664e9SAndroid Build Coastguard Worker mLastSent = timestamp;
250*d57664e9SAndroid Build Coastguard Worker }
251*d57664e9SAndroid Build Coastguard Worker
get_last_sent()252*d57664e9SAndroid Build Coastguard Worker int64_t Broadcaster::get_last_sent() {
253*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
254*d57664e9SAndroid Build Coastguard Worker return mLastSent;
255*d57664e9SAndroid Build Coastguard Worker }
256*d57664e9SAndroid Build Coastguard Worker
257*d57664e9SAndroid Build Coastguard Worker /*
258*d57664e9SAndroid Build Coastguard Worker void Broadcaster::printReportStatuses() const {
259*d57664e9SAndroid Build Coastguard Worker ALOGD("mHistory {");
260*d57664e9SAndroid Build Coastguard Worker for (map<ReportId,ReportStatus>::const_iterator it = mHistory.begin();
261*d57664e9SAndroid Build Coastguard Worker it != mHistory.end(); it++) {
262*d57664e9SAndroid Build Coastguard Worker ALOGD(" [%s %s] --> [%d %d]", it->first.id.c_str(), it->first.pkg.c_str(),
263*d57664e9SAndroid Build Coastguard Worker it->second.approval_sent, it->second.ready_sent);
264*d57664e9SAndroid Build Coastguard Worker }
265*d57664e9SAndroid Build Coastguard Worker ALOGD("}");
266*d57664e9SAndroid Build Coastguard Worker }
267*d57664e9SAndroid Build Coastguard Worker */
268*d57664e9SAndroid Build Coastguard Worker
was_approval_sent(const string & id,const string & pkg,const string & cls)269*d57664e9SAndroid Build Coastguard Worker bool Broadcaster::was_approval_sent(const string& id, const string& pkg, const string& cls) {
270*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
271*d57664e9SAndroid Build Coastguard Worker map<ReportId,ReportStatus>::const_iterator found = mHistory.find(ReportId(id, pkg, cls));
272*d57664e9SAndroid Build Coastguard Worker if (found != mHistory.end()) {
273*d57664e9SAndroid Build Coastguard Worker return found->second.approval_sent;
274*d57664e9SAndroid Build Coastguard Worker }
275*d57664e9SAndroid Build Coastguard Worker return false;
276*d57664e9SAndroid Build Coastguard Worker }
277*d57664e9SAndroid Build Coastguard Worker
set_approval_sent(const string & id,const string & pkg,const string & cls,const sp<ConsentListener> & listener)278*d57664e9SAndroid Build Coastguard Worker void Broadcaster::set_approval_sent(const string& id, const string& pkg, const string& cls,
279*d57664e9SAndroid Build Coastguard Worker const sp<ConsentListener>& listener) {
280*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
281*d57664e9SAndroid Build Coastguard Worker ReportStatus& reportStatus = mHistory[ReportId(id, pkg, cls)];
282*d57664e9SAndroid Build Coastguard Worker reportStatus.approval_sent = true;
283*d57664e9SAndroid Build Coastguard Worker reportStatus.listener = listener;
284*d57664e9SAndroid Build Coastguard Worker }
285*d57664e9SAndroid Build Coastguard Worker
was_ready_sent(const string & id,const string & pkg,const string & cls)286*d57664e9SAndroid Build Coastguard Worker bool Broadcaster::was_ready_sent(const string& id, const string& pkg, const string& cls) {
287*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
288*d57664e9SAndroid Build Coastguard Worker map<ReportId,ReportStatus>::const_iterator found = mHistory.find(ReportId(id, pkg, cls));
289*d57664e9SAndroid Build Coastguard Worker if (found != mHistory.end()) {
290*d57664e9SAndroid Build Coastguard Worker return found->second.ready_sent;
291*d57664e9SAndroid Build Coastguard Worker }
292*d57664e9SAndroid Build Coastguard Worker return false;
293*d57664e9SAndroid Build Coastguard Worker }
294*d57664e9SAndroid Build Coastguard Worker
set_ready_sent(const string & id,const string & pkg,const string & cls)295*d57664e9SAndroid Build Coastguard Worker void Broadcaster::set_ready_sent(const string& id, const string& pkg, const string& cls) {
296*d57664e9SAndroid Build Coastguard Worker unique_lock<mutex> lock(mLock);
297*d57664e9SAndroid Build Coastguard Worker mHistory[ReportId(id, pkg, cls)].ready_sent = true;
298*d57664e9SAndroid Build Coastguard Worker }
299*d57664e9SAndroid Build Coastguard Worker
send_approval_broadcasts(const string & id,const string & pkg,const string & cls)300*d57664e9SAndroid Build Coastguard Worker status_t Broadcaster::send_approval_broadcasts(const string& id, const string& pkg,
301*d57664e9SAndroid Build Coastguard Worker const string& cls) {
302*d57664e9SAndroid Build Coastguard Worker sp<IIncidentCompanion> ics = get_incident_companion();
303*d57664e9SAndroid Build Coastguard Worker if (ics == nullptr) {
304*d57664e9SAndroid Build Coastguard Worker return NAME_NOT_FOUND;
305*d57664e9SAndroid Build Coastguard Worker }
306*d57664e9SAndroid Build Coastguard Worker
307*d57664e9SAndroid Build Coastguard Worker sp<ConsentListener> listener = new ConsentListener(this, ReportId(id, pkg, cls));
308*d57664e9SAndroid Build Coastguard Worker
309*d57664e9SAndroid Build Coastguard Worker ALOGI("send_approval_broadcasts for %s %s/%s", id.c_str(), pkg.c_str(), cls.c_str());
310*d57664e9SAndroid Build Coastguard Worker
311*d57664e9SAndroid Build Coastguard Worker Status status = ics->authorizeReport(0, String16(pkg.c_str()),
312*d57664e9SAndroid Build Coastguard Worker String16(cls.c_str()), String16(id.c_str()), 0, listener);
313*d57664e9SAndroid Build Coastguard Worker
314*d57664e9SAndroid Build Coastguard Worker if (!status.isOk()) {
315*d57664e9SAndroid Build Coastguard Worker // authorizeReport is oneway, so any error is a transaction error.
316*d57664e9SAndroid Build Coastguard Worker return status.transactionError();
317*d57664e9SAndroid Build Coastguard Worker }
318*d57664e9SAndroid Build Coastguard Worker
319*d57664e9SAndroid Build Coastguard Worker set_approval_sent(id, pkg, cls, listener);
320*d57664e9SAndroid Build Coastguard Worker
321*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
322*d57664e9SAndroid Build Coastguard Worker }
323*d57664e9SAndroid Build Coastguard Worker
report_approved(const ReportId & reportId)324*d57664e9SAndroid Build Coastguard Worker void Broadcaster::report_approved(const ReportId& reportId) {
325*d57664e9SAndroid Build Coastguard Worker status_t err;
326*d57664e9SAndroid Build Coastguard Worker
327*d57664e9SAndroid Build Coastguard Worker // Kick off broadcaster to do send the ready broadcasts.
328*d57664e9SAndroid Build Coastguard Worker ALOGI("The user approved the report, so kicking off another broadcast pass. %s %s/%s",
329*d57664e9SAndroid Build Coastguard Worker reportId.id.c_str(), reportId.pkg.c_str(), reportId.cls.c_str());
330*d57664e9SAndroid Build Coastguard Worker sp<ReportFile> file = mWorkDirectory->getReport(reportId.pkg, reportId.cls, reportId.id,
331*d57664e9SAndroid Build Coastguard Worker nullptr);
332*d57664e9SAndroid Build Coastguard Worker if (file != nullptr) {
333*d57664e9SAndroid Build Coastguard Worker err = file->loadEnvelope();
334*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
335*d57664e9SAndroid Build Coastguard Worker return;
336*d57664e9SAndroid Build Coastguard Worker }
337*d57664e9SAndroid Build Coastguard Worker
338*d57664e9SAndroid Build Coastguard Worker err = file->markApproved(reportId.pkg, reportId.cls);
339*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
340*d57664e9SAndroid Build Coastguard Worker ALOGI("Couldn't find report that was just approved: %s %s/%s",
341*d57664e9SAndroid Build Coastguard Worker reportId.id.c_str(), reportId.pkg.c_str(), reportId.cls.c_str());
342*d57664e9SAndroid Build Coastguard Worker return;
343*d57664e9SAndroid Build Coastguard Worker }
344*d57664e9SAndroid Build Coastguard Worker
345*d57664e9SAndroid Build Coastguard Worker file->saveEnvelope();
346*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
347*d57664e9SAndroid Build Coastguard Worker return;
348*d57664e9SAndroid Build Coastguard Worker }
349*d57664e9SAndroid Build Coastguard Worker }
350*d57664e9SAndroid Build Coastguard Worker mReportHandler->scheduleSendBacklog();
351*d57664e9SAndroid Build Coastguard Worker }
352*d57664e9SAndroid Build Coastguard Worker
report_denied(const ReportId & reportId)353*d57664e9SAndroid Build Coastguard Worker void Broadcaster::report_denied(const ReportId& reportId) {
354*d57664e9SAndroid Build Coastguard Worker // The user didn't approve the report, so remove it from the WorkDirectory.
355*d57664e9SAndroid Build Coastguard Worker ALOGI("The user denied the report, so deleting it. %s %s/%s",
356*d57664e9SAndroid Build Coastguard Worker reportId.id.c_str(), reportId.pkg.c_str(), reportId.cls.c_str());
357*d57664e9SAndroid Build Coastguard Worker sp<ReportFile> file = mWorkDirectory->getReport(reportId.pkg, reportId.cls, reportId.id,
358*d57664e9SAndroid Build Coastguard Worker nullptr);
359*d57664e9SAndroid Build Coastguard Worker if (file != nullptr) {
360*d57664e9SAndroid Build Coastguard Worker mWorkDirectory->commit(file, reportId.pkg, reportId.cls);
361*d57664e9SAndroid Build Coastguard Worker }
362*d57664e9SAndroid Build Coastguard Worker }
363*d57664e9SAndroid Build Coastguard Worker
send_report_ready_broadcasts(const string & id,const string & pkg,const string & cls)364*d57664e9SAndroid Build Coastguard Worker status_t Broadcaster::send_report_ready_broadcasts(const string& id, const string& pkg,
365*d57664e9SAndroid Build Coastguard Worker const string& cls) {
366*d57664e9SAndroid Build Coastguard Worker sp<IIncidentCompanion> ics = get_incident_companion();
367*d57664e9SAndroid Build Coastguard Worker if (ics == nullptr) {
368*d57664e9SAndroid Build Coastguard Worker return NAME_NOT_FOUND;
369*d57664e9SAndroid Build Coastguard Worker }
370*d57664e9SAndroid Build Coastguard Worker
371*d57664e9SAndroid Build Coastguard Worker ALOGI("send_report_ready_broadcasts for %s %s/%s", id.c_str(), pkg.c_str(), cls.c_str());
372*d57664e9SAndroid Build Coastguard Worker
373*d57664e9SAndroid Build Coastguard Worker Status status = ics->sendReportReadyBroadcast(String16(pkg.c_str()), String16(cls.c_str()));
374*d57664e9SAndroid Build Coastguard Worker
375*d57664e9SAndroid Build Coastguard Worker if (!status.isOk()) {
376*d57664e9SAndroid Build Coastguard Worker // sendReportReadyBroadcast is oneway, so any error is a transaction error.
377*d57664e9SAndroid Build Coastguard Worker return status.transactionError();
378*d57664e9SAndroid Build Coastguard Worker }
379*d57664e9SAndroid Build Coastguard Worker
380*d57664e9SAndroid Build Coastguard Worker set_ready_sent(id, pkg, cls);
381*d57664e9SAndroid Build Coastguard Worker
382*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
383*d57664e9SAndroid Build Coastguard Worker }
384*d57664e9SAndroid Build Coastguard Worker
send_to_dropbox(const sp<ReportFile> & file,const IncidentReportArgs & args)385*d57664e9SAndroid Build Coastguard Worker status_t Broadcaster::send_to_dropbox(const sp<ReportFile>& file,
386*d57664e9SAndroid Build Coastguard Worker const IncidentReportArgs& args) {
387*d57664e9SAndroid Build Coastguard Worker status_t err;
388*d57664e9SAndroid Build Coastguard Worker
389*d57664e9SAndroid Build Coastguard Worker sp<DropBoxManager> dropbox = new DropBoxManager();
390*d57664e9SAndroid Build Coastguard Worker if (dropbox == nullptr) {
391*d57664e9SAndroid Build Coastguard Worker ALOGW("Can't reach dropbox now, so we won't be able to write the incident report to there");
392*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
393*d57664e9SAndroid Build Coastguard Worker }
394*d57664e9SAndroid Build Coastguard Worker
395*d57664e9SAndroid Build Coastguard Worker int fds[2];
396*d57664e9SAndroid Build Coastguard Worker if (pipe(fds) != 0) {
397*d57664e9SAndroid Build Coastguard Worker ALOGW("Error opening pipe to filter incident report: %s", file->getDataFileName().c_str());
398*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
399*d57664e9SAndroid Build Coastguard Worker }
400*d57664e9SAndroid Build Coastguard Worker
401*d57664e9SAndroid Build Coastguard Worker int readFd = fds[0];
402*d57664e9SAndroid Build Coastguard Worker int writeFd = fds[1];
403*d57664e9SAndroid Build Coastguard Worker
404*d57664e9SAndroid Build Coastguard Worker // spawn a thread to write the data. Release the writeFd ownership to the thread.
405*d57664e9SAndroid Build Coastguard Worker thread th([file, writeFd, args]() { file->startFilteringData(writeFd, args); });
406*d57664e9SAndroid Build Coastguard Worker
407*d57664e9SAndroid Build Coastguard Worker th.detach();
408*d57664e9SAndroid Build Coastguard Worker
409*d57664e9SAndroid Build Coastguard Worker // Takes ownership of readFd.
410*d57664e9SAndroid Build Coastguard Worker Status status = dropbox->addFile(String16("incident"), readFd, 0);
411*d57664e9SAndroid Build Coastguard Worker if (!status.isOk()) {
412*d57664e9SAndroid Build Coastguard Worker // TODO: This may or may not leak the readFd, depending on where it failed.
413*d57664e9SAndroid Build Coastguard Worker // Not sure how to fix this given the dropbox API.
414*d57664e9SAndroid Build Coastguard Worker ALOGW("Error sending incident report to dropbox.");
415*d57664e9SAndroid Build Coastguard Worker return -errno;
416*d57664e9SAndroid Build Coastguard Worker }
417*d57664e9SAndroid Build Coastguard Worker
418*d57664e9SAndroid Build Coastguard Worker // On successful write, tell the working directory that this file is done.
419*d57664e9SAndroid Build Coastguard Worker mWorkDirectory->commit(file, DROPBOX_SENTINEL.getPackageName(),
420*d57664e9SAndroid Build Coastguard Worker DROPBOX_SENTINEL.getClassName());
421*d57664e9SAndroid Build Coastguard Worker
422*d57664e9SAndroid Build Coastguard Worker // Don't need to call set_ready_sent, because we just removed it from the ReportFile,
423*d57664e9SAndroid Build Coastguard Worker // so we'll never hear about it again.
424*d57664e9SAndroid Build Coastguard Worker
425*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
426*d57664e9SAndroid Build Coastguard Worker }
427*d57664e9SAndroid Build Coastguard Worker
get_incident_companion()428*d57664e9SAndroid Build Coastguard Worker sp<IIncidentCompanion> Broadcaster::get_incident_companion() {
429*d57664e9SAndroid Build Coastguard Worker sp<IBinder> binder = defaultServiceManager()->getService(String16("incidentcompanion"));
430*d57664e9SAndroid Build Coastguard Worker if (binder == nullptr) {
431*d57664e9SAndroid Build Coastguard Worker ALOGI("Can not find IIncidentCompanion service to send broadcast. Will try again later.");
432*d57664e9SAndroid Build Coastguard Worker return nullptr;
433*d57664e9SAndroid Build Coastguard Worker }
434*d57664e9SAndroid Build Coastguard Worker
435*d57664e9SAndroid Build Coastguard Worker sp<IIncidentCompanion> ics = interface_cast<IIncidentCompanion>(binder);
436*d57664e9SAndroid Build Coastguard Worker if (ics == nullptr) {
437*d57664e9SAndroid Build Coastguard Worker ALOGI("The incidentcompanion service is not an IIncidentCompanion. Will try again later.");
438*d57664e9SAndroid Build Coastguard Worker return nullptr;
439*d57664e9SAndroid Build Coastguard Worker }
440*d57664e9SAndroid Build Coastguard Worker
441*d57664e9SAndroid Build Coastguard Worker return ics;
442*d57664e9SAndroid Build Coastguard Worker }
443*d57664e9SAndroid Build Coastguard Worker
444*d57664e9SAndroid Build Coastguard Worker } // namespace incidentd
445*d57664e9SAndroid Build Coastguard Worker } // namespace os
446*d57664e9SAndroid Build Coastguard Worker } // namespace android
447*d57664e9SAndroid Build Coastguard Worker
448*d57664e9SAndroid Build Coastguard Worker
449