xref: /aosp_15_r20/frameworks/base/cmds/incidentd/src/Broadcaster.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
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