diff --git a/src/plugins/android/androidsignaloperation.cpp b/src/plugins/android/androidsignaloperation.cpp index 0b44f3d5f60..8f0fbd2a7e6 100644 --- a/src/plugins/android/androidsignaloperation.cpp +++ b/src/plugins/android/androidsignaloperation.cpp @@ -1,99 +1,73 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -#include "androidconfigurations.h" #include "androidsignaloperation.h" +#include "androidconfigurations.h" + #include -#include +using namespace Tasking; using namespace Utils; +using namespace std::chrono_literals; -namespace Android { -namespace Internal { +namespace Android::Internal { -AndroidSignalOperation::AndroidSignalOperation() - : m_adbPath(AndroidConfig::adbToolPath()) - , m_timeout(new QTimer(this)) -{ - m_timeout->setInterval(5000); - connect(m_timeout, &QTimer::timeout, this, &AndroidSignalOperation::handleTimeout); -} - -AndroidSignalOperation::~AndroidSignalOperation() = default; - -bool AndroidSignalOperation::handleCrashMessage() -{ - if (m_adbProcess->exitStatus() == QProcess::NormalExit) - return false; - m_errorMessage = QLatin1String(" adb process exit code: ") + QString::number(m_adbProcess->exitCode()); - const QString adbError = m_adbProcess->errorString(); - if (!adbError.isEmpty()) - m_errorMessage += QLatin1String(" adb process error: ") + adbError; - return true; -} - -void AndroidSignalOperation::adbFindRunAsFinished() -{ - QTC_ASSERT(m_state == RunAs, return); - m_timeout->stop(); - - handleCrashMessage(); - const QString runAs = QString::fromLatin1(m_adbProcess->readAllRawStandardOutput()); - m_adbProcess.release()->deleteLater(); - if (runAs.isEmpty() || !m_errorMessage.isEmpty()) { - m_errorMessage.prepend(QLatin1String("Cannot find User for process: ") - + QString::number(m_pid)); - m_state = Idle; - emit finished(m_errorMessage); - } else { - startAdbProcess(Kill, {m_adbPath, {"shell", "run-as", runAs, "kill", - QString("-%1").arg(m_signal), QString::number(m_pid)}}, - [this] { adbKillFinished(); }); - } -} - -void AndroidSignalOperation::adbKillFinished() -{ - QTC_ASSERT(m_state == Kill, return); - m_timeout->stop(); - - if (!handleCrashMessage()) - m_errorMessage = QString::fromLatin1(m_adbProcess->readAllRawStandardError()); - m_adbProcess.release()->deleteLater(); - if (!m_errorMessage.isEmpty()) - m_errorMessage.prepend(QLatin1String("Cannot kill process: ") + QString::number(m_pid)); - m_state = Idle; - emit finished(m_errorMessage); -} - -void AndroidSignalOperation::handleTimeout() -{ - m_adbProcess.reset(); - m_timeout->stop(); - m_state = Idle; - m_errorMessage = QLatin1String("adb process timed out"); - emit finished(m_errorMessage); -} +AndroidSignalOperation::AndroidSignalOperation() = default; void AndroidSignalOperation::signalOperationViaADB(qint64 pid, int signal) { - QTC_ASSERT(m_state == Idle, return); - m_pid = pid; - m_signal = signal; - startAdbProcess(RunAs, {m_adbPath, {"shell", "cat", QString("/proc/%1/cmdline").arg(m_pid)}}, - [this] { adbFindRunAsFinished(); }); -} + struct InternalStorage { + FilePath adbPath; + QString runAs = {}; + QString errorMessage = {}; + }; -void AndroidSignalOperation::startAdbProcess(State state, const Utils::CommandLine &commandLine, - FinishHandler handler) -{ - m_state = state; - m_timeout->start(); - m_adbProcess.reset(new Process); - connect(m_adbProcess.get(), &Process::done, this, handler); - m_adbProcess->setCommand(commandLine); - m_adbProcess->start(); + const Storage storage({AndroidConfig::adbToolPath()}); + + const auto onCatSetup = [storage, pid](Process &process) { + process.setCommand({storage->adbPath, {"shell", "cat", QString("/proc/%1/cmdline").arg(pid)}}); + }; + const auto onCatDone = [storage, pid](const Process &process, DoneWith result) { + if (result == DoneWith::Success) { + storage->runAs = process.stdOut(); + if (!storage->runAs.isEmpty()) + return true; + storage->errorMessage = QLatin1String("Cannot find User for process: ") + + QString::number(pid); + } else if (result == DoneWith::Error) { + storage->errorMessage = QLatin1String(" adb process exit code: ") + + QString::number(process.exitCode()); + const QString adbError = process.errorString(); + if (!adbError.isEmpty()) + storage->errorMessage += QLatin1String(" adb process error: ") + adbError; + } else { + storage->errorMessage = QLatin1String("adb process timed out"); + } + return false; + }; + + const auto onKillSetup = [storage, pid, signal](Process &process) { + process.setCommand({storage->adbPath, {"shell", "run-as", storage->runAs, "kill", + QString("-%1").arg(signal), QString::number(pid)}}); + }; + const auto onKillDone = [storage, pid](const Process &process, DoneWith result) { + if (result == DoneWith::Error) { + storage->errorMessage = QLatin1String("Cannot kill process: ") + QString::number(pid) + + process.stdErr(); + } else if (result == DoneWith::Cancel) { + storage->errorMessage = QLatin1String("adb process timed out"); + } + }; + + const auto onDone = [this, storage] { emit finished(storage->errorMessage); }; + + const Group recipe { + ProcessTask(onCatSetup, onCatDone).withTimeout(5s), + ProcessTask(onKillSetup, onKillDone).withTimeout(5s), + onGroupDone(onDone) + }; + m_taskTreeRunner.start(recipe); } void AndroidSignalOperation::killProcess(qint64 pid) @@ -114,5 +88,4 @@ void AndroidSignalOperation::interruptProcess(qint64 pid) signalOperationViaADB(pid, 2); } -} // Internal -} // Android +} // namespace Android::Internal diff --git a/src/plugins/android/androidsignaloperation.h b/src/plugins/android/androidsignaloperation.h index 53c1d61a899..6387bd77fe3 100644 --- a/src/plugins/android/androidsignaloperation.h +++ b/src/plugins/android/androidsignaloperation.h @@ -5,16 +5,13 @@ #include -#include -#include +#include -namespace Android { -namespace Internal { +namespace Android::Internal { class AndroidSignalOperation : public ProjectExplorer::DeviceProcessSignalOperation { public: - ~AndroidSignalOperation() override; void killProcess(qint64 pid) override; void killProcess(const QString &filePath) override; void interruptProcess(qint64 pid) override; @@ -23,32 +20,11 @@ protected: explicit AndroidSignalOperation(); private: - enum State { - Idle, - RunAs, - Kill - }; - - using FinishHandler = std::function; - - bool handleCrashMessage(); - void adbFindRunAsFinished(); - void adbKillFinished(); - void handleTimeout(); - void signalOperationViaADB(qint64 pid, int signal); - void startAdbProcess(State state, const Utils::CommandLine &commandLine, FinishHandler handler); - Utils::FilePath m_adbPath; - std::unique_ptr m_adbProcess; - QTimer *m_timeout; - - State m_state = Idle; - qint64 m_pid = 0; - int m_signal = 0; + Tasking::TaskTreeRunner m_taskTreeRunner; friend class AndroidDevice; }; -} // namespace Internal -} // namespace Android +} // namespace Android::Internal