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