Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2e2bb5b8 authored by Paul Chang's avatar Paul Chang Committed by Android (Google) Code Review
Browse files

Merge "Support to screenshot to interactive bugreport." into rvc-dev

parents d9eff75a 0d2aad70
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -120,7 +120,7 @@ binder::Status DumpstateService::startBugreport(int32_t calling_uid,
    options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_fd,
                        screenshot_fd);

    if (bugreport_fd.get() == -1 || (options->do_fb && screenshot_fd.get() == -1)) {
    if (bugreport_fd.get() == -1 || (options->do_screenshot && screenshot_fd.get() == -1)) {
        MYLOGE("Invalid filedescriptor");
        signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
    }
+5 −0
Original line number Diff line number Diff line
@@ -61,4 +61,9 @@ interface IDumpstateListener {
     * Called when taking bugreport finishes successfully.
     */
    void onFinished();

    /**
     * Called when screenshot is taken.
     */
    void onScreenshotTaken(boolean success);
}
+53 −21
Original line number Diff line number Diff line
@@ -647,6 +647,24 @@ android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
    std::lock_guard<std::mutex> lock(lock_);
    result_ = APPROVED;
    MYLOGD("User approved consent to share bugreport\n");

    // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
    // consent is granted.
    if (ds.options_->is_screenshot_copied) {
        return android::binder::Status::ok();
    }

    if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
        !ds.do_early_screenshot_) {
        return android::binder::Status::ok();
    }

    bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
                                                    ds.options_->screenshot_fd.get());
    ds.options_->is_screenshot_copied = copy_succeeded;
    if (copy_succeeded) {
        android::os::UnlinkAndLogOnError(ds.screenshot_path_);
    }
    return android::binder::Status::ok();
}

@@ -1407,7 +1425,7 @@ static Dumpstate::RunStatus dumpstate() {
    /* Dump Bluetooth HCI logs */
    ds.AddDir("/data/misc/bluetooth/logs", true);

    if (ds.options_->do_fb && !ds.do_early_screenshot_) {
    if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
        MYLOGI("taking late screenshot\n");
        ds.TakeScreenshot();
    }
@@ -2149,7 +2167,7 @@ static void PrepareToWriteToFile() {
        ds.base_name_ += "-wifi";
    }

    if (ds.options_->do_fb) {
    if (ds.options_->do_screenshot) {
        ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-tmp.png" : ".png");
    }
    ds.tmp_path_ = ds.GetPath(".tmp");
@@ -2229,43 +2247,45 @@ static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
}

static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) {
    // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
    // default system screenshots.
    options->bugreport_mode = ModeToString(mode);
    switch (mode) {
        case Dumpstate::BugreportMode::BUGREPORT_FULL:
            options->do_fb = true;
            options->do_screenshot = true;
            options->dumpstate_hal_mode = DumpstateMode::FULL;
            break;
        case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
            // Currently, the dumpstate binder is only used by Shell to update progress.
            options->do_start_service = true;
            options->do_progress_updates = true;
            options->do_fb = false;
            options->do_screenshot = true;
            options->dumpstate_hal_mode = DumpstateMode::INTERACTIVE;
            break;
        case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
            options->do_vibrate = false;
            options->is_remote_mode = true;
            options->do_fb = false;
            options->do_screenshot = false;
            options->dumpstate_hal_mode = DumpstateMode::REMOTE;
            break;
        case Dumpstate::BugreportMode::BUGREPORT_WEAR:
            options->do_start_service = true;
            options->do_progress_updates = true;
            options->do_zip_file = true;
            options->do_fb = true;
            options->do_screenshot = true;
            options->dumpstate_hal_mode = DumpstateMode::WEAR;
            break;
        // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
        case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
            options->telephony_only = true;
            options->do_progress_updates = true;
            options->do_fb = false;
            options->do_screenshot = false;
            options->dumpstate_hal_mode = DumpstateMode::CONNECTIVITY;
            break;
        case Dumpstate::BugreportMode::BUGREPORT_WIFI:
            options->wifi_only = true;
            options->do_zip_file = true;
            options->do_fb = false;
            options->do_screenshot = false;
            options->dumpstate_hal_mode = DumpstateMode::WIFI;
            break;
        case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
@@ -2275,12 +2295,13 @@ static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOpt

static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
    MYLOGI(
        "do_zip_file: %d do_vibrate: %d use_socket: %d use_control_socket: %d do_fb: %d "
        "do_zip_file: %d do_vibrate: %d use_socket: %d use_control_socket: %d do_screenshot: %d "
        "is_remote_mode: %d show_header_only: %d do_start_service: %d telephony_only: %d "
        "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s dumpstate_hal_mode: %s "
        "args: %s\n",
        options.do_zip_file, options.do_vibrate, options.use_socket, options.use_control_socket,
        options.do_fb, options.is_remote_mode, options.show_header_only, options.do_start_service,
        options.do_screenshot, options.is_remote_mode, options.show_header_only,
        options.do_start_service,
        options.telephony_only, options.wifi_only, options.do_progress_updates,
        options.bugreport_fd.get(), options.bugreport_mode.c_str(),
        toString(options.dumpstate_hal_mode).c_str(), options.args.c_str());
@@ -2313,7 +2334,7 @@ Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[])
            case 'S': use_control_socket = true;     break;
            case 'v': show_header_only = true;       break;
            case 'q': do_vibrate = false;            break;
            case 'p': do_fb = true;                  break;
            case 'p': do_screenshot = true;          break;
            case 'P': do_progress_updates = true;    break;
            case 'R': is_remote_mode = true;         break;
            case 'V':                                break;  // compatibility no-op
@@ -2543,11 +2564,6 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
        Vibrate(150);
    }

    if (options_->do_fb && do_early_screenshot_) {
        MYLOGI("taking early screenshot\n");
        TakeScreenshot();
    }

    if (options_->do_zip_file && zip_file != nullptr) {
        if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
            MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
@@ -2593,19 +2609,20 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
    PrintHeader();

    if (options_->telephony_only) {
        MaybeTakeEarlyScreenshot();
        MaybeCheckUserConsent(calling_uid, calling_package);
        DumpstateTelephonyOnly(calling_package);
        DumpstateBoard();
    } else if (options_->wifi_only) {
        MaybeTakeEarlyScreenshot();
        MaybeCheckUserConsent(calling_uid, calling_package);
        DumpstateWifiOnly();
    } else {
        // Invoking the critical dumpsys calls before DumpTraces() to try and
        // keep the system stats as close to its initial state as possible.
        // Invoke critical dumpsys first to preserve system state, before doing anything else.
        RunDumpsysCritical();

        // Run consent check only after critical dumpsys has finished -- so the consent
        // isn't going to pollute the system state / logs.
        // Take screenshot and get consent only after critical dumpsys has finished.
        MaybeTakeEarlyScreenshot();
        MaybeCheckUserConsent(calling_uid, calling_package);

        // Dump state for the default case. This also drops root.
@@ -2640,7 +2657,9 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
            MYLOGI("User denied consent. Returning\n");
            return status;
        }
        if (options_->do_fb && options_->screenshot_fd.get() != -1) {
        if (options_->do_screenshot &&
            options_->screenshot_fd.get() != -1 &&
            !options_->is_screenshot_copied) {
            bool copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
                                                            options_->screenshot_fd.get());
            if (copy_succeeded) {
@@ -2694,6 +2713,14 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
               : RunStatus::OK;
}

void Dumpstate::MaybeTakeEarlyScreenshot() {
    if (!options_->do_screenshot || !do_early_screenshot_) {
        return;
    }

    TakeScreenshot();
}

void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
    if (calling_uid == AID_SHELL || !CalledByApi()) {
        // No need to get consent for shell triggered dumpstates, or not through
@@ -3630,6 +3657,11 @@ void Dumpstate::TakeScreenshot(const std::string& path) {
    } else {
        MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
    }
    if (listener_ != nullptr) {
        // Show a visual indication to indicate screenshot is taken via
        // IDumpstateListener.onScreenshotTaken()
        listener_->onScreenshotTaken(status == 0);
    }
}

bool is_dir(const char* pathname) {
+4 −1
Original line number Diff line number Diff line
@@ -359,7 +359,8 @@ class Dumpstate {
        // Writes bugreport content to a socket; only flatfile format is supported.
        bool use_socket = false;
        bool use_control_socket = false;
        bool do_fb = false;
        bool do_screenshot = false;
        bool is_screenshot_copied = false;
        bool is_remote_mode = false;
        bool show_header_only = false;
        bool do_start_service = false;
@@ -494,6 +495,8 @@ class Dumpstate {

    RunStatus DumpstateDefaultAfterCritical();

    void MaybeTakeEarlyScreenshot();

    void MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package);

    // Removes the in progress files output files (tmp file, zip/txt file, screenshot),
+6 −0
Original line number Diff line number Diff line
@@ -167,6 +167,12 @@ class DumpstateListener : public BnDumpstateListener {
        return binder::Status::ok();
    }

    binder::Status onScreenshotTaken(bool success) override {
        std::lock_guard<std::mutex> lock(lock_);
        dprintf(out_fd_, "\rResult of taking screenshot: %s", success ? "success" : "failure");
        return binder::Status::ok();
    }

    bool getIsFinished() {
        std::lock_guard<std::mutex> lock(lock_);
        return is_finished_;
Loading