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 #define LOG_TAG "incidentd"
     18 
     19 #include "IncidentService.h"
     20 
     21 #include "Reporter.h"
     22 
     23 #include <binder/IPCThreadState.h>
     24 #include <binder/IServiceManager.h>
     25 #include <cutils/log.h>
     26 #include <private/android_filesystem_config.h>
     27 #include <utils/Looper.h>
     28 
     29 #include <unistd.h>
     30 
     31 using namespace android;
     32 
     33 enum {
     34     WHAT_RUN_REPORT = 1,
     35     WHAT_SEND_BACKLOG_TO_DROPBOX = 2
     36 };
     37 
     38 //#define DEFAULT_BACKLOG_DELAY_NS (1000000000LL * 60 * 5)
     39 #define DEFAULT_BACKLOG_DELAY_NS (1000000000LL)
     40 
     41 // ================================================================================
     42 String16 const DUMP_PERMISSION("android.permission.DUMP");
     43 String16 const USAGE_STATS_PERMISSION("android.permission.PACKAGE_USAGE_STATS");
     44 
     45 static Status
     46 checkIncidentPermissions()
     47 {
     48     if (!checkCallingPermission(DUMP_PERMISSION)) {
     49         ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP",
     50                 IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
     51         return Status::fromExceptionCode(Status::EX_SECURITY,
     52                 "Calling process does not have permission: android.permission.DUMP");
     53     }
     54     if (!checkCallingPermission(USAGE_STATS_PERMISSION)) {
     55         ALOGW("Calling pid %d and uid %d does not have permission: android.permission.USAGE_STATS",
     56                 IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
     57         return Status::fromExceptionCode(Status::EX_SECURITY,
     58                 "Calling process does not have permission: android.permission.USAGE_STATS");
     59     }
     60     return Status::ok();
     61 }
     62 
     63 
     64 // ================================================================================
     65 ReportRequestQueue::ReportRequestQueue()
     66 {
     67 }
     68 
     69 ReportRequestQueue::~ReportRequestQueue()
     70 {
     71 }
     72 
     73 void
     74 ReportRequestQueue::addRequest(const sp<ReportRequest>& request)
     75 {
     76     unique_lock<mutex> lock(mLock);
     77     mQueue.push_back(request);
     78 }
     79 
     80 sp<ReportRequest>
     81 ReportRequestQueue::getNextRequest()
     82 {
     83     unique_lock<mutex> lock(mLock);
     84     if (mQueue.empty()) {
     85         return NULL;
     86     } else {
     87         sp<ReportRequest> front(mQueue.front());
     88         mQueue.pop_front();
     89         return front;
     90     }
     91 }
     92 
     93 
     94 // ================================================================================
     95 ReportHandler::ReportHandler(const sp<Looper>& handlerLooper, const sp<ReportRequestQueue>& queue)
     96     :mBacklogDelay(DEFAULT_BACKLOG_DELAY_NS),
     97      mHandlerLooper(handlerLooper),
     98      mQueue(queue)
     99 {
    100 }
    101 
    102 ReportHandler::~ReportHandler()
    103 {
    104 }
    105 
    106 void
    107 ReportHandler::handleMessage(const Message& message)
    108 {
    109     switch (message.what) {
    110         case WHAT_RUN_REPORT:
    111             run_report();
    112             break;
    113         case WHAT_SEND_BACKLOG_TO_DROPBOX:
    114             send_backlog_to_dropbox();
    115             break;
    116     }
    117 }
    118 
    119 void
    120 ReportHandler::scheduleRunReport(const sp<ReportRequest>& request)
    121 {
    122     mQueue->addRequest(request);
    123     mHandlerLooper->removeMessages(this, WHAT_RUN_REPORT);
    124     mHandlerLooper->sendMessage(this, Message(WHAT_RUN_REPORT));
    125 }
    126 
    127 void
    128 ReportHandler::scheduleSendBacklogToDropbox()
    129 {
    130     unique_lock<mutex> lock(mLock);
    131     mBacklogDelay = DEFAULT_BACKLOG_DELAY_NS;
    132     schedule_send_backlog_to_dropbox_locked();
    133 }
    134 
    135 void
    136 ReportHandler::schedule_send_backlog_to_dropbox_locked()
    137 {
    138     mHandlerLooper->removeMessages(this, WHAT_SEND_BACKLOG_TO_DROPBOX);
    139     mHandlerLooper->sendMessageDelayed(mBacklogDelay, this,
    140             Message(WHAT_SEND_BACKLOG_TO_DROPBOX));
    141 }
    142 
    143 void
    144 ReportHandler::run_report()
    145 {
    146     sp<Reporter> reporter = new Reporter();
    147 
    148     // Merge all of the requests into one that has all of the
    149     // requested fields.
    150     while (true) {
    151         sp<ReportRequest> request = mQueue->getNextRequest();
    152         if (request == NULL) {
    153             break;
    154         }
    155         reporter->batch.add(request);
    156         reporter->args.merge(request->args);
    157     }
    158 
    159     // Take the report, which might take a while. More requests might queue
    160     // up while we're doing this, and we'll handle them in their next batch.
    161     // TODO: We should further rate-limit the reports to no more than N per time-period.
    162     Reporter::run_report_status_t reportStatus = reporter->runReport();
    163     if (reportStatus == Reporter::REPORT_NEEDS_DROPBOX) {
    164         unique_lock<mutex> lock(mLock);
    165         schedule_send_backlog_to_dropbox_locked();
    166     }
    167 }
    168 
    169 void
    170 ReportHandler::send_backlog_to_dropbox()
    171 {
    172     if (Reporter::upload_backlog() == Reporter::REPORT_NEEDS_DROPBOX) {
    173         // There was a failure. Exponential backoff.
    174         unique_lock<mutex> lock(mLock);
    175         mBacklogDelay *= 2;
    176         ALOGI("Error sending to dropbox. Trying again in %lld minutes",
    177                 (mBacklogDelay / (1000000000LL * 60)));
    178         schedule_send_backlog_to_dropbox_locked();
    179     } else {
    180         mBacklogDelay = DEFAULT_BACKLOG_DELAY_NS;
    181     }
    182 }
    183 
    184 // ================================================================================
    185 IncidentService::IncidentService(const sp<Looper>& handlerLooper)
    186     :mQueue(new ReportRequestQueue())
    187 {
    188     mHandler = new ReportHandler(handlerLooper, mQueue);
    189 }
    190 
    191 IncidentService::~IncidentService()
    192 {
    193 }
    194 
    195 Status
    196 IncidentService::reportIncident(const IncidentReportArgs& args)
    197 {
    198     ALOGI("reportIncident");
    199 
    200     Status status = checkIncidentPermissions();
    201     if (!status.isOk()) {
    202         return status;
    203     }
    204 
    205     mHandler->scheduleRunReport(new ReportRequest(args, NULL, -1));
    206 
    207     return Status::ok();
    208 }
    209 
    210 Status
    211 IncidentService::reportIncidentToStream(const IncidentReportArgs& args,
    212             const sp<IIncidentReportStatusListener>& listener, const unique_fd& stream)
    213 {
    214     ALOGI("reportIncidentToStream");
    215 
    216     Status status = checkIncidentPermissions();
    217     if (!status.isOk()) {
    218         return status;
    219     }
    220 
    221     int fd = dup(stream.get());
    222     if (fd < 0) {
    223         return Status::fromStatusT(-errno);
    224     }
    225 
    226     mHandler->scheduleRunReport(new ReportRequest(args, listener, fd));
    227 
    228     return Status::ok();
    229 }
    230 
    231 Status
    232 IncidentService::systemRunning()
    233 {
    234     if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
    235         return Status::fromExceptionCode(Status::EX_SECURITY,
    236                 "Only system uid can call systemRunning");
    237     }
    238 
    239     // When system_server is up and running, schedule the dropbox task to run.
    240     mHandler->scheduleSendBacklogToDropbox();
    241 
    242     return Status::ok();
    243 }
    244 
    245