/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#define DEBUG false
#include "Log.h"

#include "IncidentService.h"

#include "FdBuffer.h"
#include "PrivacyFilter.h"
#include "Reporter.h"
#include "incidentd_util.h"
#include "section_list.h"

#include <android/os/IncidentReportArgs.h>
#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
#include <binder/IServiceManager.h>
#include <binder/IShellCallback.h>
#include <log/log.h>
#include <private/android_filesystem_config.h>
#include <utils/Looper.h>
#include <thread>

#include <unistd.h>

enum {
    WHAT_TAKE_REPORT = 1,
    WHAT_SEND_BROADCASTS = 2
};

#define DEFAULT_DELAY_NS (1000000000LL)

#define DEFAULT_BYTES_SIZE_LIMIT (400 * 1024 * 1024)        // 400MB
#define DEFAULT_REFACTORY_PERIOD_MS (24 * 60 * 60 * 1000)  // 1 Day

// Skip these sections (for dumpstate only)
// Skip logs (1100 - 1108), traces (1200 - 1202), dumpsys (3000 - 3024, 3027 - 3056, 4000 - 4001)
// because they are already in the bug report.
#define SKIPPED_DUMPSTATE_SECTIONS { \
            1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, /* Logs */ \
            1200, 1201, 1202, /* Native, hal, java traces */ \
            3018, /* dumpsys meminfo*/ }

namespace android {
namespace os {
namespace incidentd {

String16 const APPROVE_INCIDENT_REPORTS("android.permission.APPROVE_INCIDENT_REPORTS");
String16 const DUMP_PERMISSION("android.permission.DUMP");
String16 const USAGE_STATS_PERMISSION("android.permission.PACKAGE_USAGE_STATS");

static Status checkIncidentPermissions(const IncidentReportArgs& args) {
    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    pid_t callingPid = IPCThreadState::self()->getCallingPid();
    if (callingUid == AID_ROOT || callingUid == AID_SHELL) {
        // Root and shell are ok.
        return Status::ok();
    }

    if (checkCallingPermission(APPROVE_INCIDENT_REPORTS)) {
        // Permission controller (this is a singleton permission that is always granted
        // exactly for PermissionController) is allowed to access incident reports
        // so it can show the user info about what they are approving.
        return Status::ok();
    }

    // checking calling permission.
    if (!checkCallingPermission(DUMP_PERMISSION)) {
        ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP",
              callingPid, callingUid);
        return Status::fromExceptionCode(
                Status::EX_SECURITY,
                "Calling process does not have permission: android.permission.DUMP");
    }
    if (!checkCallingPermission(USAGE_STATS_PERMISSION)) {
        ALOGW("Calling pid %d and uid %d does not have permission: android.permission.USAGE_STATS",
              callingPid, callingUid);
        return Status::fromExceptionCode(
                Status::EX_SECURITY,
                "Calling process does not have permission: android.permission.USAGE_STATS");
    }

    // checking calling request uid permission.
    switch (args.getPrivacyPolicy()) {
        case PRIVACY_POLICY_LOCAL:
            if (callingUid != AID_SHELL && callingUid != AID_ROOT) {
                ALOGW("Calling pid %d and uid %d does not have permission to get local data.",
                      callingPid, callingUid);
                return Status::fromExceptionCode(
                        Status::EX_SECURITY,
                        "Calling process does not have permission to get local data.");
            }
            break;
        case PRIVACY_POLICY_EXPLICIT:
            if (callingUid != AID_SHELL && callingUid != AID_ROOT && callingUid != AID_STATSD &&
                    callingUid != AID_SYSTEM) {
                ALOGW("Calling pid %d and uid %d does not have permission to get explicit data.",
                      callingPid, callingUid);
                return Status::fromExceptionCode(
                        Status::EX_SECURITY,
                        "Calling process does not have permission to get explicit data.");
            }
            break;
    }
    return Status::ok();
}

static string build_uri(const string& pkg, const string& cls, const string& id) {
    return "content://android.os.IncidentManager/pending?pkg="
        + pkg + "&receiver=" + cls + "&r=" + id;
}

// ================================================================================
ReportHandler::ReportHandler(const sp<WorkDirectory>& workDirectory,
                             const sp<Broadcaster>& broadcaster,
                             const sp<Looper>& handlerLooper,
                             const sp<Throttler>& throttler,
                             const vector<BringYourOwnSection*>& registeredSections)
        :mLock(),
         mWorkDirectory(workDirectory),
         mBroadcaster(broadcaster),
         mHandlerLooper(handlerLooper),
         mBacklogDelay(DEFAULT_DELAY_NS),
         mThrottler(throttler),
         mRegisteredSections(registeredSections),
         mBatch(new ReportBatch()) {
}

ReportHandler::~ReportHandler() {
}

void ReportHandler::handleMessage(const Message& message) {
    switch (message.what) {
        case WHAT_TAKE_REPORT:
            take_report();
            break;
        case WHAT_SEND_BROADCASTS:
            send_broadcasts();
            break;
    }
}

void ReportHandler::schedulePersistedReport(const IncidentReportArgs& args) {
    unique_lock<mutex> lock(mLock);
    mBatch->addPersistedReport(args);
    mHandlerLooper->removeMessages(this, WHAT_TAKE_REPORT);
    mHandlerLooper->sendMessage(this, Message(WHAT_TAKE_REPORT));
}

void ReportHandler::scheduleStreamingReport(const IncidentReportArgs& args,
        const sp<IIncidentReportStatusListener>& listener, int streamFd) {
    unique_lock<mutex> lock(mLock);
    mBatch->addStreamingReport(args, listener, streamFd);
    mHandlerLooper->removeMessages(this, WHAT_TAKE_REPORT);
    mHandlerLooper->sendMessage(this, Message(WHAT_TAKE_REPORT));
}

void ReportHandler::scheduleSendBacklog() {
    unique_lock<mutex> lock(mLock);
    mBacklogDelay = DEFAULT_DELAY_NS;
    schedule_send_broadcasts_locked();
}

void ReportHandler::schedule_send_broadcasts_locked() {
    mHandlerLooper->removeMessages(this, WHAT_SEND_BROADCASTS);
    mHandlerLooper->sendMessageDelayed(mBacklogDelay, this, Message(WHAT_SEND_BROADCASTS));
}

void ReportHandler::take_report() {
    // Cycle the batch and throttle.
    sp<ReportBatch> batch;
    {
        unique_lock<mutex> lock(mLock);
        batch = mThrottler->filterBatch(mBatch);
    }

    if (batch->empty()) {
        // Nothing to do.
        return;
    }

    sp<Reporter> reporter = new Reporter(mWorkDirectory, batch, mRegisteredSections);

    // Take the report, which might take a while. More requests might queue
    // up while we're doing this, and we'll handle them in their next batch.
    // TODO: We should further rate-limit the reports to no more than N per time-period.
    // TODO: Move this inside reporter.
    size_t reportByteSize = 0;
    reporter->runReport(&reportByteSize);

    // Tell the throttler how big it was, for the next throttling.
    // TODO: This still isn't ideal. The throttler really should just track the
    // persisted reqeusts, but changing Reporter::runReport() to track that individually
    // will be a big change.
    if (batch->hasPersistedReports()) {
        mThrottler->addReportSize(reportByteSize);
    }

    // Kick off the next steps, one of which is to send any new or otherwise remaining
    // approvals, and one of which is to send any new or remaining broadcasts.
    {
        unique_lock<mutex> lock(mLock);
        schedule_send_broadcasts_locked();
    }
}

void ReportHandler::send_broadcasts() {
    Broadcaster::broadcast_status_t result = mBroadcaster->sendBroadcasts();
    if (result == Broadcaster::BROADCASTS_FINISHED) {
        // We're done.
        unique_lock<mutex> lock(mLock);
        mBacklogDelay = DEFAULT_DELAY_NS;
    } else if (result == Broadcaster::BROADCASTS_REPEAT) {
        // It worked, but there are more.
        unique_lock<mutex> lock(mLock);
        mBacklogDelay = DEFAULT_DELAY_NS;
        schedule_send_broadcasts_locked();
    } else if (result == Broadcaster::BROADCASTS_BACKOFF) {
        // There was a failure. Exponential backoff.
        unique_lock<mutex> lock(mLock);
        mBacklogDelay *= 2;
        ALOGI("Error sending to dropbox. Trying again in %lld minutes",
              (mBacklogDelay / (1000000000LL * 60)));
        schedule_send_broadcasts_locked();
    }
}

// ================================================================================
IncidentService::IncidentService(const sp<Looper>& handlerLooper) {
    mThrottler = new Throttler(DEFAULT_BYTES_SIZE_LIMIT, DEFAULT_REFACTORY_PERIOD_MS);
    mWorkDirectory = new WorkDirectory();
    mBroadcaster = new Broadcaster(mWorkDirectory);
    mHandler = new ReportHandler(mWorkDirectory, mBroadcaster, handlerLooper,
            mThrottler, mRegisteredSections);
    mBroadcaster->setHandler(mHandler);
}

IncidentService::~IncidentService() {}

Status IncidentService::reportIncident(const IncidentReportArgs& args) {
    IncidentReportArgs argsCopy(args);

    // Validate that the privacy policy is one of the real ones.
    // If it isn't, clamp it to the next more restrictive real one.
    argsCopy.setPrivacyPolicy(cleanup_privacy_policy(args.getPrivacyPolicy()));

    // TODO: Check that the broadcast recevier has the proper permissions
    // TODO: Maybe we should consider relaxing the permissions if it's going to
    // dropbox, but definitely not if it's going to the broadcaster.
    Status status = checkIncidentPermissions(args);
    if (!status.isOk()) {
        return status;
    }

    // If they asked for the LOCAL privacy policy, give them EXPLICT.  LOCAL has to
    // be streamed. (This only applies to shell/root, because everyone else would have
    // been rejected by checkIncidentPermissions()).
    if (argsCopy.getPrivacyPolicy() < PRIVACY_POLICY_EXPLICIT) {
        ALOGI("Demoting privacy policy to EXPLICT for persisted report.");
        argsCopy.setPrivacyPolicy(PRIVACY_POLICY_EXPLICIT);
    }

    // If they didn't specify a component, use dropbox.
    if (argsCopy.receiverPkg().length() == 0 && argsCopy.receiverCls().length() == 0) {
        argsCopy.setReceiverPkg(DROPBOX_SENTINEL.getPackageName());
        argsCopy.setReceiverCls(DROPBOX_SENTINEL.getClassName());
    }

    mHandler->schedulePersistedReport(argsCopy);

    return Status::ok();
}

Status IncidentService::reportIncidentToStream(const IncidentReportArgs& args,
                                               const sp<IIncidentReportStatusListener>& listener,
                                               unique_fd stream) {
    IncidentReportArgs argsCopy(args);

    // Streaming reports can not also be broadcast.
    argsCopy.setReceiverPkg("");
    argsCopy.setReceiverCls("");

    // Validate that the privacy policy is one of the real ones.
    // If it isn't, clamp it to the next more restrictive real one.
    argsCopy.setPrivacyPolicy(cleanup_privacy_policy(args.getPrivacyPolicy()));

    Status status = checkIncidentPermissions(argsCopy);
    if (!status.isOk()) {
        return status;
    }

    // The ReportRequest takes ownership of the fd, so we need to dup it.
    int fd = dup(stream.get());
    if (fd < 0) {
        return Status::fromStatusT(-errno);
    }

    mHandler->scheduleStreamingReport(argsCopy, listener, fd);

    return Status::ok();
}

Status IncidentService::reportIncidentToDumpstate(unique_fd stream,
        const sp<IIncidentReportStatusListener>& listener) {
    uid_t caller = IPCThreadState::self()->getCallingUid();
    if (caller != AID_ROOT && caller != AID_SHELL) {
        ALOGW("Calling uid %d does not have permission: only ROOT or SHELL allowed", caller);
        return Status::fromExceptionCode(Status::EX_SECURITY, "Only ROOT or SHELL allowed");
    }

    ALOGD("Stream incident report to dumpstate");
    IncidentReportArgs incidentArgs;
    // Privacy policy for dumpstate incident reports is always EXPLICIT.
    incidentArgs.setPrivacyPolicy(PRIVACY_POLICY_EXPLICIT);

    int skipped[] = SKIPPED_DUMPSTATE_SECTIONS;
    for (const Section** section = SECTION_LIST; *section; section++) {
        const int id = (*section)->id;
        if (std::find(std::begin(skipped), std::end(skipped), id) == std::end(skipped)
                && !section_requires_specific_mention(id)) {
            incidentArgs.addSection(id);
        }
    }
    for (const Section* section : mRegisteredSections) {
        if (!section_requires_specific_mention(section->id)) {
            incidentArgs.addSection(section->id);
        }
    }

    // The ReportRequest takes ownership of the fd, so we need to dup it.
    int fd = dup(stream.get());
    if (fd < 0) {
        return Status::fromStatusT(-errno);
    }

    mHandler->scheduleStreamingReport(incidentArgs, listener, fd);

    return Status::ok();
}

Status IncidentService::registerSection(const int id, const String16& name16,
        const sp<IIncidentDumpCallback>& callback) {
    const String8 name = String8(name16);
    const uid_t callingUid = IPCThreadState::self()->getCallingUid();
    ALOGI("Uid %d registers section %d '%s'", callingUid, id, name.c_str());
    if (callback == nullptr) {
        return Status::fromExceptionCode(Status::EX_NULL_POINTER);
    }
    for (int i = 0; i < mRegisteredSections.size(); i++) {
        if (mRegisteredSections.at(i)->id == id) {
            if (mRegisteredSections.at(i)->uid != callingUid) {
                ALOGW("Error registering section %d: calling uid does not match", id);
                return Status::fromExceptionCode(Status::EX_SECURITY);
            }
            mRegisteredSections.at(i) = new BringYourOwnSection(id, name.c_str(), callingUid, callback);
            return Status::ok();
        }
    }
    mRegisteredSections.push_back(new BringYourOwnSection(id, name.c_str(), callingUid, callback));
    return Status::ok();
}

Status IncidentService::unregisterSection(const int id) {
    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    ALOGI("Uid %d unregisters section %d", callingUid, id);

    for (auto it = mRegisteredSections.begin(); it != mRegisteredSections.end(); it++) {
        if ((*it)->id == id) {
            if ((*it)->uid != callingUid) {
                ALOGW("Error unregistering section %d: calling uid does not match", id);
                return Status::fromExceptionCode(Status::EX_SECURITY);
            }
            mRegisteredSections.erase(it);
            return Status::ok();
        }
    }
    ALOGW("Section %d not found", id);
    return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
}

Status IncidentService::systemRunning() {
    if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
        return Status::fromExceptionCode(Status::EX_SECURITY,
                                         "Only system uid can call systemRunning");
    }

    // When system_server is up and running, schedule the dropbox task to run.
    mBroadcaster->reset();
    mHandler->scheduleSendBacklog();

    return Status::ok();
}

Status IncidentService::getIncidentReportList(const String16& pkg16, const String16& cls16,
            vector<String16>* result) {
    status_t err;
    const string pkg(String8(pkg16).c_str());
    const string cls(String8(cls16).c_str());

    // List the reports
    vector<sp<ReportFile>> all;
    err = mWorkDirectory->getReports(&all, 0);
    if (err != NO_ERROR) {
        return Status::fromStatusT(err);
    }

    // Find the ones that match pkg and cls.
    for (sp<ReportFile>& file: all) {
        err = file->loadEnvelope();
        if (err != NO_ERROR) {
            continue;
        }
        const ReportFileProto& envelope = file->getEnvelope();
        size_t reportCount = envelope.report_size();
        for (int reportIndex = 0; reportIndex < reportCount; reportIndex++) {
            const ReportFileProto_Report& report = envelope.report(reportIndex);
            if (pkg == report.pkg() && cls == report.cls()) {
                result->push_back(String16(build_uri(pkg, cls, file->getId()).c_str()));
                break;
            }
        }
    }

    return Status::ok();
}

Status IncidentService::getIncidentReport(const String16& pkg16, const String16& cls16,
            const String16& id16, IncidentManager::IncidentReport* result) {
    status_t err;

    const string pkg(String8(pkg16).c_str());
    const string cls(String8(cls16).c_str());
    const string id(String8(id16).c_str());

    IncidentReportArgs args;
    sp<ReportFile> file = mWorkDirectory->getReport(pkg, cls, id, &args);
    if (file != nullptr) {
        // Create pipe
        int fds[2];
        if (pipe(fds) != 0) {
            ALOGW("Error opening pipe to filter incident report: %s",
                  file->getDataFileName().c_str());
            return Status::ok();
        }
        result->setTimestampNs(file->getTimestampNs());
        result->setPrivacyPolicy(file->getEnvelope().privacy_policy());
        result->takeFileDescriptor(fds[0]);
        int writeFd = fds[1];
        // spawn a thread to write the data. Release the writeFd ownership to the thread.
        thread th([file, writeFd, args]() { file->startFilteringData(writeFd, args); });

        th.detach();
    }

    return Status::ok();
}

Status IncidentService::deleteIncidentReports(const String16& pkg16, const String16& cls16,
            const String16& id16) {
    const string pkg(String8(pkg16).c_str());
    const string cls(String8(cls16).c_str());
    const string id(String8(id16).c_str());

    sp<ReportFile> file = mWorkDirectory->getReport(pkg, cls, id, nullptr);
    if (file != nullptr) {
        mWorkDirectory->commit(file, pkg, cls);
    }
    mBroadcaster->clearBroadcasts(pkg, cls, id);

    return Status::ok();
}

Status IncidentService::deleteAllIncidentReports(const String16& pkg16) {
    const string pkg(String8(pkg16).c_str());

    mWorkDirectory->commitAll(pkg);
    mBroadcaster->clearPackageBroadcasts(pkg);

    return Status::ok();
}

/**
 * Implement our own because the default binder implementation isn't
 * properly handling SHELL_COMMAND_TRANSACTION.
 */
status_t IncidentService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                     uint32_t flags) {
    status_t err;

    switch (code) {
        case SHELL_COMMAND_TRANSACTION: {
            unique_fd in, out, err;
            if (status_t status = data.readUniqueFileDescriptor(&in); status != OK) return status;

            if (status_t status = data.readUniqueFileDescriptor(&out); status != OK) return status;

            if (status_t status = data.readUniqueFileDescriptor(&err); status != OK) return status;

            int argc = data.readInt32();
            Vector<String8> args;
            for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
                args.add(String8(data.readString16()));
            }
            sp<IShellCallback> shellCallback = IShellCallback::asInterface(data.readStrongBinder());
            sp<IResultReceiver> resultReceiver =
                    IResultReceiver::asInterface(data.readStrongBinder());
            if (resultReceiver == nullptr) {
                return BAD_VALUE;
            }

            FILE* fin = fdopen(in.release(), "r");
            FILE* fout = fdopen(out.release(), "w");
            FILE* ferr = fdopen(err.release(), "w");

            if (fin == NULL || fout == NULL || ferr == NULL) {
                resultReceiver->send(NO_MEMORY);
            } else {
                status_t result = command(fin, fout, ferr, args);
                resultReceiver->send(result);
            }

            if (fin != NULL) {
                fflush(fin);
                fclose(fin);
            }
            if (fout != NULL) {
                fflush(fout);
                fclose(fout);
            }
            if (ferr != NULL) {
                fflush(ferr);
                fclose(ferr);
            }

            return NO_ERROR;
        } break;
        default: { return BnIncidentManager::onTransact(code, data, reply, flags); }
    }
}

status_t IncidentService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
    const int argCount = args.size();

    if (argCount >= 1) {
        if (!args[0].compare(String8("privacy"))) {
            return cmd_privacy(in, out, err, args);
        }
        if (!args[0].compare(String8("throttler"))) {
            mThrottler->dump(out);
            return NO_ERROR;
        }
        if (!args[0].compare(String8("section"))) {
            if (argCount == 1) {
                fprintf(out, "Not enough arguments for section\n");
                return NO_ERROR;
            }
            int id = atoi(args[1].c_str());
            int idx = 0;
            while (SECTION_LIST[idx] != NULL) {
                const Section* section = SECTION_LIST[idx];
                if (section->id == id) {
                    fprintf(out, "Section[%d] %s\n", id, section->name.c_str());
                    break;
                }
                idx++;
            }
            return NO_ERROR;
        }
    }
    return cmd_help(out);
}

status_t IncidentService::cmd_help(FILE* out) {
    fprintf(out, "usage: adb shell cmd incident privacy print <section_id>\n");
    fprintf(out, "usage: adb shell cmd incident privacy parse <section_id> < proto.txt\n");
    fprintf(out, "    Prints/parses for the section id.\n\n");
    fprintf(out, "usage: adb shell cmd incident section <section_id>\n");
    fprintf(out, "    Prints section id and its name.\n\n");
    fprintf(out, "usage: adb shell cmd incident throttler\n");
    fprintf(out, "    Prints the current throttler state\n");
    return NO_ERROR;
}

static void printPrivacy(const Privacy* p, FILE* out, String8 indent) {
    if (p == NULL) return;
    fprintf(out, "%sid:%d, type:%d, dest:%d\n", indent.c_str(), p->field_id, p->type, p->policy);
    if (p->children == NULL) return;
    for (int i = 0; p->children[i] != NULL; i++) {  // NULL-terminated.
        printPrivacy(p->children[i], out, indent + "  ");
    }
}

status_t IncidentService::cmd_privacy(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
    (void)in;

    const int argCount = args.size();
    if (argCount >= 3) {
        String8 opt = args[1];
        int sectionId = atoi(args[2].c_str());

        const Privacy* p = get_privacy_of_section(sectionId);
        if (p == NULL) {
            fprintf(err, "Can't find section id %d\n", sectionId);
            return NO_ERROR;
        }
        fprintf(err, "Get privacy for %d\n", sectionId);
        if (opt == "print") {
            printPrivacy(p, out, String8(""));
        } else if (opt == "parse") {
            /*
            FdBuffer buf;
            status_t error = buf.read(fileno(in), 60000);
            if (error != NO_ERROR) {
                fprintf(err, "Error reading from stdin\n");
                return error;
            }
            fprintf(err, "Read %zu bytes\n", buf.size());
            PrivacyFilter pBuf(p, buf.data());

            PrivacySpec spec = PrivacySpec::new_spec(argCount > 3 ? atoi(args[3]) : -1);
            error = pBuf.strip(spec);
            if (error != NO_ERROR) {
                fprintf(err, "Error strip pii fields with spec %d\n", spec.policy);
                return error;
            }
            return pBuf.flush(fileno(out));
            */
            return -1;
        }
    } else {
        return cmd_help(out);
    }
    return NO_ERROR;
}

}  // namespace incidentd
}  // namespace os
}  // namespace android
