forked from qt-creator/qt-creator
Android: Move the AndroidRunnerWorker to the main thread
Replace AndroidRunnerWorker with runnerRecipe(). Add RunnerInterface for communication between AndroidRunner and runnerRecipe(). Get rid of a separate thread. Change-Id: I32a651592859b762b0e52a2d44c28652d42566bb Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -44,14 +44,12 @@ AndroidRunner::AndroidRunner(RunControl *runControl)
|
|||||||
this, &AndroidRunner::qmlServerPortReady);
|
this, &AndroidRunner::qmlServerPortReady);
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidRunner::~AndroidRunner()
|
|
||||||
{
|
|
||||||
m_thread.quit();
|
|
||||||
m_thread.wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidRunner::start()
|
void AndroidRunner::start()
|
||||||
{
|
{
|
||||||
|
const Storage<RunnerInterface> glueStorage;
|
||||||
|
|
||||||
|
std::optional<ExecutableItem> avdRecipe;
|
||||||
|
|
||||||
QString deviceSerialNumber;
|
QString deviceSerialNumber;
|
||||||
int apiLevel = -1;
|
int apiLevel = -1;
|
||||||
|
|
||||||
@@ -69,56 +67,49 @@ void AndroidRunner::start()
|
|||||||
if (!info.avdName.isEmpty()) {
|
if (!info.avdName.isEmpty()) {
|
||||||
const Storage<QString> serialNumberStorage;
|
const Storage<QString> serialNumberStorage;
|
||||||
|
|
||||||
const Group recipe {
|
avdRecipe = Group {
|
||||||
serialNumberStorage,
|
serialNumberStorage,
|
||||||
AndroidAvdManager::startAvdRecipe(info.avdName, serialNumberStorage)
|
AndroidAvdManager::startAvdRecipe(info.avdName, serialNumberStorage)
|
||||||
};
|
}.withCancel([glueStorage] {
|
||||||
|
return std::make_pair(glueStorage.activeStorage(), &RunnerInterface::canceled);
|
||||||
m_startAvdRunner.start(recipe, {}, [this, deviceSerialNumber, apiLevel](DoneWith result) {
|
|
||||||
if (result == DoneWith::Success)
|
|
||||||
startImpl(deviceSerialNumber, apiLevel);
|
|
||||||
});
|
});
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
deviceSerialNumber = AndroidManager::deviceSerialNumber(m_target);
|
deviceSerialNumber = AndroidManager::deviceSerialNumber(m_target);
|
||||||
apiLevel = AndroidManager::deviceApiLevel(m_target);
|
apiLevel = AndroidManager::deviceApiLevel(m_target);
|
||||||
}
|
}
|
||||||
startImpl(deviceSerialNumber, apiLevel);
|
|
||||||
|
const auto onSetup = [this, glueStorage, deviceSerialNumber, apiLevel] {
|
||||||
|
RunnerInterface *glue = glueStorage.activeStorage();
|
||||||
|
glue->setRunControl(runControl());
|
||||||
|
glue->setDeviceSerialNumber(deviceSerialNumber);
|
||||||
|
glue->setApiLevel(apiLevel);
|
||||||
|
|
||||||
|
connect(this, &AndroidRunner::canceled, glue, &RunnerInterface::cancel);
|
||||||
|
|
||||||
|
connect(glue, &RunnerInterface::started, this, &AndroidRunner::remoteStarted);
|
||||||
|
connect(glue, &RunnerInterface::finished, this, &AndroidRunner::remoteFinished);
|
||||||
|
connect(glue, &RunnerInterface::stdOut, this, &AndroidRunner::remoteStdOut);
|
||||||
|
connect(glue, &RunnerInterface::stdErr, this, &AndroidRunner::remoteStdErr);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Group recipe {
|
||||||
|
glueStorage,
|
||||||
|
onGroupSetup(onSetup),
|
||||||
|
avdRecipe ? *avdRecipe : nullItem,
|
||||||
|
runnerRecipe(glueStorage)
|
||||||
|
};
|
||||||
|
m_taskTreeRunner.start(recipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidRunner::stop()
|
void AndroidRunner::stop()
|
||||||
{
|
{
|
||||||
if (m_startAvdRunner.isRunning()) {
|
if (!m_taskTreeRunner.isRunning())
|
||||||
m_startAvdRunner.reset();
|
|
||||||
appendMessage("\n\n" + Tr::tr("\"%1\" terminated.").arg(AndroidManager::packageName(m_target)),
|
|
||||||
Utils::NormalMessageFormat);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
emit asyncStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidRunner::startImpl(const QString &deviceSerialNumber, int apiLevel)
|
emit canceled();
|
||||||
{
|
appendMessage("\n\n" + Tr::tr("\"%1\" terminated.").arg(AndroidManager::packageName(m_target)),
|
||||||
if (m_worker)
|
Utils::NormalMessageFormat);
|
||||||
m_worker->deleteLater();
|
|
||||||
|
|
||||||
m_worker = new AndroidRunnerWorker(runControl(), deviceSerialNumber, apiLevel);
|
|
||||||
m_worker->moveToThread(&m_thread);
|
|
||||||
QObject::connect(&m_thread, &QThread::finished, m_worker, &QObject::deleteLater);
|
|
||||||
|
|
||||||
connect(this, &AndroidRunner::asyncStop, m_worker, &AndroidRunnerWorker::asyncStop);
|
|
||||||
|
|
||||||
connect(m_worker, &AndroidRunnerWorker::remoteProcessStarted,
|
|
||||||
this, &AndroidRunner::handleRemoteProcessStarted);
|
|
||||||
connect(m_worker, &AndroidRunnerWorker::remoteProcessFinished,
|
|
||||||
this, &AndroidRunner::handleRemoteProcessFinished);
|
|
||||||
connect(m_worker, &AndroidRunnerWorker::remoteOutput, this, &AndroidRunner::remoteOutput);
|
|
||||||
connect(m_worker, &AndroidRunnerWorker::remoteErrorOutput,
|
|
||||||
this, &AndroidRunner::remoteErrorOutput);
|
|
||||||
|
|
||||||
m_thread.start();
|
|
||||||
QMetaObject::invokeMethod(m_worker, &AndroidRunnerWorker::asyncStart);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidRunner::qmlServerPortReady(Port port)
|
void AndroidRunner::qmlServerPortReady(Port port)
|
||||||
@@ -134,20 +125,7 @@ void AndroidRunner::qmlServerPortReady(Port port)
|
|||||||
emit qmlServerReady(serverUrl);
|
emit qmlServerReady(serverUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidRunner::remoteOutput(const QString &output)
|
void AndroidRunner::remoteStarted(const Port &debugServerPort, const QUrl &qmlServer, qint64 pid)
|
||||||
{
|
|
||||||
appendMessage(output, Utils::StdOutFormat);
|
|
||||||
m_outputParser.processOutput(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidRunner::remoteErrorOutput(const QString &output)
|
|
||||||
{
|
|
||||||
appendMessage(output, Utils::StdErrFormat);
|
|
||||||
m_outputParser.processOutput(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidRunner::handleRemoteProcessStarted(Utils::Port debugServerPort,
|
|
||||||
const QUrl &qmlServer, qint64 pid)
|
|
||||||
{
|
{
|
||||||
m_pid = ProcessHandle(pid);
|
m_pid = ProcessHandle(pid);
|
||||||
m_debugServerPort = debugServerPort;
|
m_debugServerPort = debugServerPort;
|
||||||
@@ -155,7 +133,7 @@ void AndroidRunner::handleRemoteProcessStarted(Utils::Port debugServerPort,
|
|||||||
reportStarted();
|
reportStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidRunner::handleRemoteProcessFinished(const QString &errString)
|
void AndroidRunner::remoteFinished(const QString &errString)
|
||||||
{
|
{
|
||||||
appendMessage(errString, Utils::NormalMessageFormat);
|
appendMessage(errString, Utils::NormalMessageFormat);
|
||||||
if (runControl()->isRunning())
|
if (runControl()->isRunning())
|
||||||
@@ -163,4 +141,16 @@ void AndroidRunner::handleRemoteProcessFinished(const QString &errString)
|
|||||||
reportStopped();
|
reportStopped();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AndroidRunner::remoteStdOut(const QString &output)
|
||||||
|
{
|
||||||
|
appendMessage(output, Utils::StdOutFormat);
|
||||||
|
m_outputParser.processOutput(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidRunner::remoteStdErr(const QString &output)
|
||||||
|
{
|
||||||
|
appendMessage(output, Utils::StdErrFormat);
|
||||||
|
m_outputParser.processOutput(output);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Android::Internal
|
} // namespace Android::Internal
|
||||||
|
@@ -12,19 +12,14 @@
|
|||||||
|
|
||||||
#include <solutions/tasking/tasktreerunner.h>
|
#include <solutions/tasking/tasktreerunner.h>
|
||||||
|
|
||||||
#include <QThread>
|
|
||||||
|
|
||||||
namespace Android::Internal {
|
namespace Android::Internal {
|
||||||
|
|
||||||
class AndroidRunnerWorker;
|
|
||||||
|
|
||||||
class AndroidRunner : public ProjectExplorer::RunWorker
|
class AndroidRunner : public ProjectExplorer::RunWorker
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AndroidRunner(ProjectExplorer::RunControl *runControl);
|
explicit AndroidRunner(ProjectExplorer::RunControl *runControl);
|
||||||
~AndroidRunner() override;
|
|
||||||
|
|
||||||
Utils::Port debugServerPort() const { return m_debugServerPort; } // GDB or LLDB
|
Utils::Port debugServerPort() const { return m_debugServerPort; } // GDB or LLDB
|
||||||
QUrl qmlServer() const { return m_qmlServer; }
|
QUrl qmlServer() const { return m_qmlServer; }
|
||||||
@@ -34,27 +29,24 @@ public:
|
|||||||
void stop() override;
|
void stop() override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void asyncStop();
|
void canceled();
|
||||||
void qmlServerReady(const QUrl &serverUrl);
|
void qmlServerReady(const QUrl &serverUrl);
|
||||||
void avdDetected();
|
void avdDetected();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void startImpl(const QString &deviceSerialNumber, int apiLevel);
|
|
||||||
void qmlServerPortReady(Utils::Port port);
|
void qmlServerPortReady(Utils::Port port);
|
||||||
void remoteOutput(const QString &output);
|
|
||||||
void remoteErrorOutput(const QString &output);
|
|
||||||
void gotRemoteOutput(const QString &output);
|
|
||||||
void handleRemoteProcessStarted(Utils::Port debugServerPort, const QUrl &qmlServer, qint64 pid);
|
|
||||||
void handleRemoteProcessFinished(const QString &errString = QString());
|
|
||||||
|
|
||||||
QThread m_thread;
|
void remoteStarted(const Utils::Port &debugServerPort, const QUrl &qmlServer, qint64 pid);
|
||||||
AndroidRunnerWorker *m_worker = nullptr;
|
void remoteFinished(const QString &errString);
|
||||||
|
void remoteStdOut(const QString &output);
|
||||||
|
void remoteStdErr(const QString &output);
|
||||||
|
|
||||||
QPointer<ProjectExplorer::Target> m_target;
|
QPointer<ProjectExplorer::Target> m_target;
|
||||||
Utils::Port m_debugServerPort;
|
Utils::Port m_debugServerPort;
|
||||||
QUrl m_qmlServer;
|
QUrl m_qmlServer;
|
||||||
Utils::ProcessHandle m_pid;
|
Utils::ProcessHandle m_pid;
|
||||||
QmlDebug::QmlOutputParser m_outputParser;
|
QmlDebug::QmlOutputParser m_outputParser;
|
||||||
Tasking::TaskTreeRunner m_startAvdRunner;
|
Tasking::TaskTreeRunner m_taskTreeRunner;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Android::Internal
|
} // namespace Android::Internal
|
||||||
|
@@ -131,10 +131,8 @@ static FilePath debugServer(bool useLldb, const Target *target)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
class RunnerStorage : public QObject
|
class RunnerStorage
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QStringList selector() const { return AndroidDeviceInfo::adbSelector(m_deviceSerialNumber); }
|
QStringList selector() const { return AndroidDeviceInfo::adbSelector(m_deviceSerialNumber); }
|
||||||
bool isPreNougat() const { return m_apiLevel > 0 && m_apiLevel <= 23; }
|
bool isPreNougat() const { return m_apiLevel > 0 && m_apiLevel <= 23; }
|
||||||
@@ -154,6 +152,8 @@ public:
|
|||||||
return QStringList{"shell", "run-as", m_packageName} + userArgs();
|
return QStringList{"shell", "run-as", m_packageName} + userArgs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RunnerInterface *m_glue = nullptr;
|
||||||
|
|
||||||
QString m_packageName;
|
QString m_packageName;
|
||||||
QString m_intentName;
|
QString m_intentName;
|
||||||
QStringList m_beforeStartAdbCommands;
|
QStringList m_beforeStartAdbCommands;
|
||||||
@@ -165,30 +165,21 @@ public:
|
|||||||
bool m_useLldb = false;
|
bool m_useLldb = false;
|
||||||
QmlDebug::QmlDebugServicesPreset m_qmlDebugServices;
|
QmlDebug::QmlDebugServicesPreset m_qmlDebugServices;
|
||||||
QUrl m_qmlServer;
|
QUrl m_qmlServer;
|
||||||
QString m_deviceSerialNumber;
|
QString m_deviceSerialNumber; // TODO: remove
|
||||||
int m_apiLevel = -1;
|
int m_apiLevel = -1; // TODO: remove
|
||||||
QString m_extraAppParams;
|
QString m_extraAppParams;
|
||||||
Utils::Environment m_extraEnvVars;
|
Utils::Environment m_extraEnvVars;
|
||||||
Utils::FilePath m_debugServerPath; // On build device, typically as part of ndk
|
Utils::FilePath m_debugServerPath; // On build device, typically as part of ndk
|
||||||
bool m_useAppParamsForQmlDebugger = false;
|
bool m_useAppParamsForQmlDebugger = false;
|
||||||
|
|
||||||
signals:
|
|
||||||
void remoteProcessStarted(Utils::Port debugServerPort, const QUrl &qmlServer, qint64 pid);
|
|
||||||
void remoteProcessFinished(const QString &errString = QString());
|
|
||||||
|
|
||||||
void remoteOutput(const QString &output);
|
|
||||||
void remoteErrorOutput(const QString &output);
|
|
||||||
|
|
||||||
void cancel();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void setupStorage(RunnerStorage *storage, RunControl *runControl,
|
static void setupStorage(RunnerStorage *storage, RunnerInterface *glue)
|
||||||
const QString &deviceSerialNumber, int apiLevel)
|
|
||||||
{
|
{
|
||||||
storage->m_useLldb = Debugger::DebuggerKitAspect::engineType(runControl->kit())
|
storage->m_glue = glue;
|
||||||
|
storage->m_useLldb = Debugger::DebuggerKitAspect::engineType(glue->runControl()->kit())
|
||||||
== Debugger::LldbEngineType;
|
== Debugger::LldbEngineType;
|
||||||
auto aspect = runControl->aspectData<Debugger::DebuggerRunConfigurationAspect>();
|
auto aspect = glue->runControl()->aspectData<Debugger::DebuggerRunConfigurationAspect>();
|
||||||
const Id runMode = runControl->runMode();
|
const Id runMode = glue->runControl()->runMode();
|
||||||
const bool debuggingMode = runMode == ProjectExplorer::Constants::DEBUG_RUN_MODE;
|
const bool debuggingMode = runMode == ProjectExplorer::Constants::DEBUG_RUN_MODE;
|
||||||
storage->m_useCppDebugger = debuggingMode && aspect->useCppDebugger;
|
storage->m_useCppDebugger = debuggingMode && aspect->useCppDebugger;
|
||||||
if (debuggingMode && aspect->useQmlDebugger)
|
if (debuggingMode && aspect->useQmlDebugger)
|
||||||
@@ -212,30 +203,30 @@ static void setupStorage(RunnerStorage *storage, RunControl *runControl,
|
|||||||
qCDebug(androidRunWorkerLog) << "QML server:" << storage->m_qmlServer.toDisplayString();
|
qCDebug(androidRunWorkerLog) << "QML server:" << storage->m_qmlServer.toDisplayString();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto target = runControl->target();
|
auto target = glue->runControl()->target();
|
||||||
storage->m_packageName = AndroidManager::packageName(target);
|
storage->m_packageName = AndroidManager::packageName(target);
|
||||||
storage->m_intentName = storage->m_packageName + '/' + AndroidManager::activityName(target);
|
storage->m_intentName = storage->m_packageName + '/' + AndroidManager::activityName(target);
|
||||||
storage->m_deviceSerialNumber = deviceSerialNumber;
|
storage->m_deviceSerialNumber = glue->deviceSerialNumber();
|
||||||
storage->m_apiLevel = apiLevel;
|
storage->m_apiLevel = glue->apiLevel();
|
||||||
qCDebug(androidRunWorkerLog) << "Intent name:" << storage->m_intentName
|
qCDebug(androidRunWorkerLog) << "Intent name:" << storage->m_intentName
|
||||||
<< "Package name:" << storage->m_packageName;
|
<< "Package name:" << storage->m_packageName;
|
||||||
qCDebug(androidRunWorkerLog) << "Device API:" << storage->m_apiLevel;
|
qCDebug(androidRunWorkerLog) << "Device API:" << storage->m_apiLevel;
|
||||||
|
|
||||||
storage->m_extraEnvVars = runControl->aspectData<EnvironmentAspect>()->environment;
|
storage->m_extraEnvVars = glue->runControl()->aspectData<EnvironmentAspect>()->environment;
|
||||||
qCDebug(androidRunWorkerLog).noquote() << "Environment variables for the app"
|
qCDebug(androidRunWorkerLog).noquote() << "Environment variables for the app"
|
||||||
<< storage->m_extraEnvVars.toStringList();
|
<< storage->m_extraEnvVars.toStringList();
|
||||||
|
|
||||||
if (target->buildConfigurations().first()->buildType() != BuildConfiguration::BuildType::Release)
|
if (target->buildConfigurations().first()->buildType() != BuildConfiguration::BuildType::Release)
|
||||||
storage->m_extraAppParams = runControl->commandLine().arguments();
|
storage->m_extraAppParams = glue->runControl()->commandLine().arguments();
|
||||||
|
|
||||||
if (const Store sd = runControl->settingsData(Constants::ANDROID_AM_START_ARGS);
|
if (const Store sd = glue->runControl()->settingsData(Constants::ANDROID_AM_START_ARGS);
|
||||||
!sd.isEmpty()) {
|
!sd.isEmpty()) {
|
||||||
QTC_CHECK(sd.first().typeId() == QMetaType::QString);
|
QTC_CHECK(sd.first().typeId() == QMetaType::QString);
|
||||||
const QString startArgs = sd.first().toString();
|
const QString startArgs = sd.first().toString();
|
||||||
storage->m_amStartExtraArgs = ProcessArgs::splitArgs(startArgs, OsTypeOtherUnix);
|
storage->m_amStartExtraArgs = ProcessArgs::splitArgs(startArgs, OsTypeOtherUnix);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const Store sd = runControl->settingsData(Constants::ANDROID_PRESTARTSHELLCMDLIST);
|
if (const Store sd = glue->runControl()->settingsData(Constants::ANDROID_PRESTARTSHELLCMDLIST);
|
||||||
!sd.isEmpty()) {
|
!sd.isEmpty()) {
|
||||||
const QVariant &first = sd.first();
|
const QVariant &first = sd.first();
|
||||||
QTC_CHECK(first.typeId() == QMetaType::QStringList);
|
QTC_CHECK(first.typeId() == QMetaType::QStringList);
|
||||||
@@ -244,7 +235,7 @@ static void setupStorage(RunnerStorage *storage, RunControl *runControl,
|
|||||||
storage->m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd));
|
storage->m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const Store sd = runControl->settingsData(Constants::ANDROID_POSTFINISHSHELLCMDLIST);
|
if (const Store sd = glue->runControl()->settingsData(Constants::ANDROID_POSTFINISHSHELLCMDLIST);
|
||||||
!sd.isEmpty()) {
|
!sd.isEmpty()) {
|
||||||
const QVariant &first = sd.first();
|
const QVariant &first = sd.first();
|
||||||
QTC_CHECK(first.typeId() == QMetaType::QStringList);
|
QTC_CHECK(first.typeId() == QMetaType::QStringList);
|
||||||
@@ -265,27 +256,7 @@ static void setupStorage(RunnerStorage *storage, RunControl *runControl,
|
|||||||
storage->m_useAppParamsForQmlDebugger = version->qtVersion() >= QVersionNumber(5, 12);
|
storage->m_useAppParamsForQmlDebugger = version->qtVersion() >= QVersionNumber(5, 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidRunnerWorker::AndroidRunnerWorker(RunControl *runControl, const QString &deviceSerialNumber,
|
static ExecutableItem forceStopRecipe(const Storage<RunnerStorage> &storage)
|
||||||
int apiLevel)
|
|
||||||
: m_storage(new RunnerStorage)
|
|
||||||
{
|
|
||||||
m_storage->setParent(this); // Move m_storage object together with *this into a separate thread.
|
|
||||||
setupStorage(m_storage.get(), runControl, deviceSerialNumber, apiLevel);
|
|
||||||
m_taskTreeRunner.setParent(this); // Move m_taskTreeRunner object together with *this into a separate thread.
|
|
||||||
|
|
||||||
connect(m_storage.get(), &RunnerStorage::remoteProcessStarted,
|
|
||||||
this, &AndroidRunnerWorker::remoteProcessStarted);
|
|
||||||
connect(m_storage.get(), &RunnerStorage::remoteProcessFinished,
|
|
||||||
this, &AndroidRunnerWorker::remoteProcessFinished);
|
|
||||||
connect(m_storage.get(), &RunnerStorage::remoteOutput,
|
|
||||||
this, &AndroidRunnerWorker::remoteOutput);
|
|
||||||
connect(m_storage.get(), &RunnerStorage::remoteErrorOutput,
|
|
||||||
this, &AndroidRunnerWorker::remoteErrorOutput);
|
|
||||||
|
|
||||||
connect(this, &AndroidRunnerWorker::cancel, m_storage.get(), &RunnerStorage::cancel);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ExecutableItem forceStopRecipe(RunnerStorage *storage)
|
|
||||||
{
|
{
|
||||||
const auto onForceStopSetup = [storage](Process &process) {
|
const auto onForceStopSetup = [storage](Process &process) {
|
||||||
process.setCommand(storage->adbCommand({"shell", "am", "force-stop", storage->m_packageName}));
|
process.setCommand(storage->adbCommand({"shell", "am", "force-stop", storage->m_packageName}));
|
||||||
@@ -335,7 +306,7 @@ static ExecutableItem removeForwardPortRecipe(RunnerStorage *storage, const QStr
|
|||||||
process.setCommand(storage->adbCommand({"forward", "--remove", port}));
|
process.setCommand(storage->adbCommand({"forward", "--remove", port}));
|
||||||
};
|
};
|
||||||
const auto onForwardRemoveDone = [storage](const Process &process) {
|
const auto onForwardRemoveDone = [storage](const Process &process) {
|
||||||
emit storage->remoteErrorOutput(process.cleanedStdErr().trimmed());
|
storage->m_glue->addStdErr(process.cleanedStdErr().trimmed());
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -346,7 +317,7 @@ static ExecutableItem removeForwardPortRecipe(RunnerStorage *storage, const QStr
|
|||||||
if (result == DoneWith::Success)
|
if (result == DoneWith::Success)
|
||||||
storage->m_afterFinishAdbCommands.push_back("forward --remove " + port);
|
storage->m_afterFinishAdbCommands.push_back("forward --remove " + port);
|
||||||
else
|
else
|
||||||
emit storage->remoteProcessFinished(Tr::tr("Failed to forward %1 debugging ports.").arg(portType));
|
storage->m_glue->setFinished(Tr::tr("Failed to forward %1 debugging ports.").arg(portType));
|
||||||
};
|
};
|
||||||
|
|
||||||
return Group {
|
return Group {
|
||||||
@@ -359,7 +330,8 @@ static ExecutableItem removeForwardPortRecipe(RunnerStorage *storage, const QStr
|
|||||||
|
|
||||||
// The startBarrier is passed when logcat process received "Sending WAIT chunk" message.
|
// The startBarrier is passed when logcat process received "Sending WAIT chunk" message.
|
||||||
// The settledBarrier is passed when logcat process received "debugger has settled" message.
|
// The settledBarrier is passed when logcat process received "debugger has settled" message.
|
||||||
static ExecutableItem jdbRecipe(RunnerStorage *storage, const SingleBarrier &startBarrier,
|
static ExecutableItem jdbRecipe(const Storage<RunnerStorage> &storage,
|
||||||
|
const SingleBarrier &startBarrier,
|
||||||
const SingleBarrier &settledBarrier)
|
const SingleBarrier &settledBarrier)
|
||||||
{
|
{
|
||||||
const auto onSetup = [storage] {
|
const auto onSetup = [storage] {
|
||||||
@@ -367,9 +339,9 @@ static ExecutableItem jdbRecipe(RunnerStorage *storage, const SingleBarrier &sta
|
|||||||
};
|
};
|
||||||
|
|
||||||
const auto onTaskTreeSetup = [storage](TaskTree &taskTree) {
|
const auto onTaskTreeSetup = [storage](TaskTree &taskTree) {
|
||||||
taskTree.setRecipe({
|
taskTree.setRecipe({removeForwardPortRecipe(storage.activeStorage(),
|
||||||
removeForwardPortRecipe(storage, "tcp:" + s_localJdbServerPort.toString(),
|
"tcp:" + s_localJdbServerPort.toString(),
|
||||||
"jdwp:" + QString::number(storage->m_processPID), "JDB")
|
"jdwp:" + QString::number(storage->m_processPID), "JDB")
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -403,7 +375,7 @@ static ExecutableItem jdbRecipe(RunnerStorage *storage, const SingleBarrier &sta
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ExecutableItem logcatRecipe(RunnerStorage *storage)
|
static ExecutableItem logcatRecipe(const Storage<RunnerStorage> &storage)
|
||||||
{
|
{
|
||||||
struct Buffer {
|
struct Buffer {
|
||||||
QStringList timeArgs;
|
QStringList timeArgs;
|
||||||
@@ -424,11 +396,12 @@ static ExecutableItem logcatRecipe(RunnerStorage *storage)
|
|||||||
};
|
};
|
||||||
|
|
||||||
const auto onLogcatSetup = [storage, bufferStorage, startJdbBarrier, settledJdbBarrier](Process &process) {
|
const auto onLogcatSetup = [storage, bufferStorage, startJdbBarrier, settledJdbBarrier](Process &process) {
|
||||||
|
RunnerStorage *storagePtr = storage.activeStorage();
|
||||||
Buffer *bufferPtr = bufferStorage.activeStorage();
|
Buffer *bufferPtr = bufferStorage.activeStorage();
|
||||||
const auto parseLogcat = [storage, bufferPtr, start = startJdbBarrier->barrier(),
|
const auto parseLogcat = [storagePtr, bufferPtr, start = startJdbBarrier->barrier(),
|
||||||
settled = settledJdbBarrier->barrier(), processPtr = &process](
|
settled = settledJdbBarrier->barrier(), processPtr = &process](
|
||||||
QProcess::ProcessChannel channel) {
|
QProcess::ProcessChannel channel) {
|
||||||
if (storage->m_processPID == -1)
|
if (storagePtr->m_processPID == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QByteArray &buffer = channel == QProcess::StandardOutput ? bufferPtr->stdOutBuffer
|
QByteArray &buffer = channel == QProcess::StandardOutput ? bufferPtr->stdOutBuffer
|
||||||
@@ -444,13 +417,13 @@ static ExecutableItem logcatRecipe(RunnerStorage *storage)
|
|||||||
else
|
else
|
||||||
buffer = lines.takeLast(); // incomplete line
|
buffer = lines.takeLast(); // incomplete line
|
||||||
|
|
||||||
const QString pidString = QString::number(storage->m_processPID);
|
const QString pidString = QString::number(storagePtr->m_processPID);
|
||||||
for (const QByteArray &msg : std::as_const(lines)) {
|
for (const QByteArray &msg : std::as_const(lines)) {
|
||||||
const QString line = QString::fromUtf8(msg).trimmed() + QLatin1Char('\n');
|
const QString line = QString::fromUtf8(msg).trimmed() + QLatin1Char('\n');
|
||||||
if (!line.contains(pidString))
|
if (!line.contains(pidString))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (storage->m_useCppDebugger) {
|
if (storagePtr->m_useCppDebugger) {
|
||||||
if (start->current() == 0 && msg.trimmed().endsWith("Sending WAIT chunk"))
|
if (start->current() == 0 && msg.trimmed().endsWith("Sending WAIT chunk"))
|
||||||
start->advance();
|
start->advance();
|
||||||
else if (settled->current() == 0 && msg.indexOf("debugger has settled") > 0)
|
else if (settled->current() == 0 && msg.indexOf("debugger has settled") > 0)
|
||||||
@@ -481,16 +454,16 @@ static ExecutableItem logcatRecipe(RunnerStorage *storage)
|
|||||||
const QString msgType = match.captured(2);
|
const QString msgType = match.captured(2);
|
||||||
const QString output = line.mid(match.capturedStart(2));
|
const QString output = line.mid(match.capturedStart(2));
|
||||||
if (onlyError || msgType == "F" || msgType == "E" || msgType == "W")
|
if (onlyError || msgType == "F" || msgType == "E" || msgType == "W")
|
||||||
emit storage->remoteErrorOutput(output);
|
storagePtr->m_glue->addStdErr(output);
|
||||||
else
|
else
|
||||||
emit storage->remoteOutput(output);
|
storagePtr->m_glue->addStdOut(output);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (onlyError || line.startsWith("F/") || line.startsWith("E/")
|
if (onlyError || line.startsWith("F/") || line.startsWith("E/")
|
||||||
|| line.startsWith("W/")) {
|
|| line.startsWith("W/")) {
|
||||||
emit storage->remoteErrorOutput(line);
|
storagePtr->m_glue->addStdErr(line);
|
||||||
} else {
|
} else {
|
||||||
emit storage->remoteOutput(line);
|
storagePtr->m_glue->addStdOut(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -517,12 +490,12 @@ static ExecutableItem logcatRecipe(RunnerStorage *storage)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ExecutableItem preStartRecipe(RunnerStorage *storage)
|
static ExecutableItem preStartRecipe(const Storage<RunnerStorage> &storage)
|
||||||
{
|
{
|
||||||
const QString port = "tcp:" + QString::number(storage->m_qmlServer.port());
|
|
||||||
|
|
||||||
const Storage<QStringList> argsStorage;
|
const Storage<QStringList> argsStorage;
|
||||||
const LoopList iterator(storage->m_beforeStartAdbCommands);
|
const LoopUntil iterator([storage](int iteration) {
|
||||||
|
return iteration < storage->m_beforeStartAdbCommands.size();
|
||||||
|
});
|
||||||
|
|
||||||
const auto onArgsSetup = [storage, argsStorage] {
|
const auto onArgsSetup = [storage, argsStorage] {
|
||||||
*argsStorage = {"shell", "am", "start", "-n", storage->m_intentName};
|
*argsStorage = {"shell", "am", "start", "-n", storage->m_intentName};
|
||||||
@@ -531,15 +504,20 @@ static ExecutableItem preStartRecipe(RunnerStorage *storage)
|
|||||||
};
|
};
|
||||||
|
|
||||||
const auto onPreCommandSetup = [storage, iterator](Process &process) {
|
const auto onPreCommandSetup = [storage, iterator](Process &process) {
|
||||||
process.setCommand(storage->adbCommand({iterator->split(' ', Qt::SkipEmptyParts)}));
|
process.setCommand(storage->adbCommand(
|
||||||
|
{storage->m_beforeStartAdbCommands.at(iterator.iteration()).split(' ', Qt::SkipEmptyParts)}));
|
||||||
};
|
};
|
||||||
const auto onPreCommandDone = [storage](const Process &process) {
|
const auto onPreCommandDone = [storage](const Process &process) {
|
||||||
emit storage->remoteErrorOutput(process.cleanedStdErr().trimmed());
|
storage->m_glue->addStdErr(process.cleanedStdErr().trimmed());
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto onQmlDebugSetup = [storage] {
|
const auto onQmlDebugSetup = [storage] {
|
||||||
return storage->m_qmlDebugServices == QmlDebug::NoQmlDebugServices ? SetupResult::StopWithSuccess
|
return storage->m_qmlDebugServices == QmlDebug::NoQmlDebugServices
|
||||||
: SetupResult::Continue;
|
? SetupResult::StopWithSuccess : SetupResult::Continue;
|
||||||
|
};
|
||||||
|
const auto onTaskTreeSetup = [storage](TaskTree &taskTree) {
|
||||||
|
const QString port = "tcp:" + QString::number(storage->m_qmlServer.port());
|
||||||
|
taskTree.setRecipe({removeForwardPortRecipe(storage.activeStorage(), port, port, "QML")});
|
||||||
};
|
};
|
||||||
const auto onQmlDebugDone = [storage, argsStorage] {
|
const auto onQmlDebugDone = [storage, argsStorage] {
|
||||||
const QString qmljsdebugger = QString("port:%1,block,services:%2")
|
const QString qmljsdebugger = QString("port:%1,block,services:%2")
|
||||||
@@ -575,8 +553,8 @@ static ExecutableItem preStartRecipe(RunnerStorage *storage)
|
|||||||
process.setCommand(storage->adbCommand({args}));
|
process.setCommand(storage->adbCommand({args}));
|
||||||
};
|
};
|
||||||
const auto onActivityDone = [storage](const Process &process) {
|
const auto onActivityDone = [storage](const Process &process) {
|
||||||
emit storage->remoteProcessFinished(Tr::tr("Activity Manager error: %1")
|
storage->m_glue->setFinished(
|
||||||
.arg(process.cleanedStdErr().trimmed()));
|
Tr::tr("Activity Manager error: %1").arg(process.cleanedStdErr().trimmed()));
|
||||||
};
|
};
|
||||||
|
|
||||||
return Group {
|
return Group {
|
||||||
@@ -587,14 +565,14 @@ static ExecutableItem preStartRecipe(RunnerStorage *storage)
|
|||||||
},
|
},
|
||||||
Group {
|
Group {
|
||||||
onGroupSetup(onQmlDebugSetup),
|
onGroupSetup(onQmlDebugSetup),
|
||||||
removeForwardPortRecipe(storage, port, port, "QML"),
|
TaskTreeTask(onTaskTreeSetup),
|
||||||
onGroupDone(onQmlDebugDone, CallDoneIf::Success)
|
onGroupDone(onQmlDebugDone, CallDoneIf::Success)
|
||||||
},
|
},
|
||||||
ProcessTask(onActivitySetup, onActivityDone, CallDoneIf::Error)
|
ProcessTask(onActivitySetup, onActivityDone, CallDoneIf::Error)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ExecutableItem postDoneRecipe(RunnerStorage *storage)
|
static ExecutableItem postDoneRecipe(const Storage<RunnerStorage> &storage)
|
||||||
{
|
{
|
||||||
const LoopUntil iterator([storage](int iteration) {
|
const LoopUntil iterator([storage](int iteration) {
|
||||||
return iteration < storage->m_afterFinishAdbCommands.size();
|
return iteration < storage->m_afterFinishAdbCommands.size();
|
||||||
@@ -608,7 +586,7 @@ static ExecutableItem postDoneRecipe(RunnerStorage *storage)
|
|||||||
const auto onDone = [storage] {
|
const auto onDone = [storage] {
|
||||||
storage->m_processPID = -1;
|
storage->m_processPID = -1;
|
||||||
storage->m_processUser = -1;
|
storage->m_processUser = -1;
|
||||||
emit storage->remoteProcessFinished("\n\n" + Tr::tr("\"%1\" died.").arg(storage->m_packageName));
|
storage->m_glue->setFinished("\n\n" + Tr::tr("\"%1\" died.").arg(storage->m_packageName));
|
||||||
};
|
};
|
||||||
|
|
||||||
return Group {
|
return Group {
|
||||||
@@ -626,7 +604,8 @@ static QString tempDebugServerPath(int count)
|
|||||||
return tempDebugServerPathTemplate.arg(count);
|
return tempDebugServerPathTemplate.arg(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ExecutableItem uploadDebugServerRecipe(RunnerStorage *storage, const QString &debugServerFileName)
|
static ExecutableItem uploadDebugServerRecipe(const Storage<RunnerStorage> &storage,
|
||||||
|
const QString &debugServerFileName)
|
||||||
{
|
{
|
||||||
const Storage<QString> tempDebugServerPathStorage;
|
const Storage<QString> tempDebugServerPathStorage;
|
||||||
const LoopUntil iterator([tempDebugServerPathStorage](int iteration) {
|
const LoopUntil iterator([tempDebugServerPathStorage](int iteration) {
|
||||||
@@ -645,8 +624,8 @@ static ExecutableItem uploadDebugServerRecipe(RunnerStorage *storage, const QStr
|
|||||||
const auto onTempDebugServerPath = [storage, tempDebugServerPathStorage] {
|
const auto onTempDebugServerPath = [storage, tempDebugServerPathStorage] {
|
||||||
const bool tempDirOK = !tempDebugServerPathStorage->isEmpty();
|
const bool tempDirOK = !tempDebugServerPathStorage->isEmpty();
|
||||||
if (tempDirOK) {
|
if (tempDirOK) {
|
||||||
emit storage->remoteProcessStarted(s_localDebugServerPort, storage->m_qmlServer,
|
storage->m_glue->setStarted(s_localDebugServerPort, storage->m_qmlServer,
|
||||||
storage->m_processPID);
|
storage->m_processPID);
|
||||||
} else {
|
} else {
|
||||||
qCDebug(androidRunWorkerLog) << "Can not get temporary file name";
|
qCDebug(androidRunWorkerLog) << "Can not get temporary file name";
|
||||||
}
|
}
|
||||||
@@ -693,7 +672,7 @@ static ExecutableItem uploadDebugServerRecipe(RunnerStorage *storage, const QStr
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ExecutableItem startNativeDebuggingRecipe(RunnerStorage *storage)
|
static ExecutableItem startNativeDebuggingRecipe(const Storage<RunnerStorage> &storage)
|
||||||
{
|
{
|
||||||
const auto onSetup = [storage] {
|
const auto onSetup = [storage] {
|
||||||
return storage->m_useCppDebugger ? SetupResult::Continue : SetupResult::StopWithSuccess;
|
return storage->m_useCppDebugger ? SetupResult::Continue : SetupResult::StopWithSuccess;
|
||||||
@@ -709,7 +688,7 @@ static ExecutableItem startNativeDebuggingRecipe(RunnerStorage *storage)
|
|||||||
if (result == DoneWith::Success)
|
if (result == DoneWith::Success)
|
||||||
*packageDirStorage = process.stdOut();
|
*packageDirStorage = process.stdOut();
|
||||||
else
|
else
|
||||||
emit storage->remoteProcessFinished(Tr::tr("Failed to find application directory."));
|
storage->m_glue->setFinished(Tr::tr("Failed to find application directory."));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add executable flag to package dir. Gdb can't connect to running server on device on
|
// Add executable flag to package dir. Gdb can't connect to running server on device on
|
||||||
@@ -723,7 +702,7 @@ static ExecutableItem startNativeDebuggingRecipe(RunnerStorage *storage)
|
|||||||
QString msg = Tr::tr("Cannot find C++ debug server in NDK installation.");
|
QString msg = Tr::tr("Cannot find C++ debug server in NDK installation.");
|
||||||
if (storage->m_useLldb)
|
if (storage->m_useLldb)
|
||||||
msg += "\n" + Tr::tr("The lldb-server binary has not been found.");
|
msg += "\n" + Tr::tr("The lldb-server binary has not been found.");
|
||||||
emit storage->remoteProcessFinished(msg);
|
storage->m_glue->setFinished(msg);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -742,7 +721,7 @@ static ExecutableItem startNativeDebuggingRecipe(RunnerStorage *storage)
|
|||||||
setDebugServer(debugServerFileName)
|
setDebugServer(debugServerFileName)
|
||||||
} >> Else {
|
} >> Else {
|
||||||
Sync([storage] {
|
Sync([storage] {
|
||||||
emit storage->remoteProcessFinished(Tr::tr("Cannot copy C++ debug server."));
|
storage->m_glue->setFinished(Tr::tr("Cannot copy C++ debug server."));
|
||||||
return false;
|
return false;
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
@@ -776,7 +755,8 @@ static ExecutableItem startNativeDebuggingRecipe(RunnerStorage *storage)
|
|||||||
|
|
||||||
const auto onTaskTreeSetup = [storage, packageDirStorage](TaskTree &taskTree) {
|
const auto onTaskTreeSetup = [storage, packageDirStorage](TaskTree &taskTree) {
|
||||||
const QString gdbServerSocket = *packageDirStorage + "/debug-socket";
|
const QString gdbServerSocket = *packageDirStorage + "/debug-socket";
|
||||||
taskTree.setRecipe({removeForwardPortRecipe(storage, "tcp:" + s_localDebugServerPort.toString(),
|
taskTree.setRecipe({removeForwardPortRecipe(storage.activeStorage(),
|
||||||
|
"tcp:" + s_localDebugServerPort.toString(),
|
||||||
"localfilesystem:" + gdbServerSocket, "C++")});
|
"localfilesystem:" + gdbServerSocket, "C++")});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -813,13 +793,12 @@ static ExecutableItem startNativeDebuggingRecipe(RunnerStorage *storage)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ExecutableItem pidRecipe(RunnerStorage *storage)
|
static ExecutableItem pidRecipe(const Storage<RunnerStorage> &storage)
|
||||||
{
|
{
|
||||||
const QString pidScript = storage->isPreNougat()
|
const auto onPidSetup = [storage](Process &process) {
|
||||||
? QString("for p in /proc/[0-9]*; do cat <$p/cmdline && echo :${p##*/}; done")
|
const QString pidScript = storage->isPreNougat()
|
||||||
: QString("pidof -s '%1'").arg(storage->m_packageName);
|
? QString("for p in /proc/[0-9]*; do cat <$p/cmdline && echo :${p##*/}; done")
|
||||||
|
: QString("pidof -s '%1'").arg(storage->m_packageName);
|
||||||
const auto onPidSetup = [storage, pidScript](Process &process) {
|
|
||||||
process.setCommand(storage->adbCommand({"shell", pidScript}));
|
process.setCommand(storage->adbCommand({"shell", pidScript}));
|
||||||
};
|
};
|
||||||
const auto onPidDone = [storage](const Process &process) {
|
const auto onPidDone = [storage](const Process &process) {
|
||||||
@@ -848,8 +827,8 @@ static ExecutableItem pidRecipe(RunnerStorage *storage)
|
|||||||
storage->m_processUser = processUser;
|
storage->m_processUser = processUser;
|
||||||
qCDebug(androidRunWorkerLog) << "Process ID changed to:" << storage->m_processPID;
|
qCDebug(androidRunWorkerLog) << "Process ID changed to:" << storage->m_processPID;
|
||||||
if (!storage->m_useCppDebugger) {
|
if (!storage->m_useCppDebugger) {
|
||||||
emit storage->remoteProcessStarted(s_localDebugServerPort, storage->m_qmlServer,
|
storage->m_glue->setStarted(s_localDebugServerPort, storage->m_qmlServer,
|
||||||
storage->m_processPID);
|
storage->m_processPID);
|
||||||
}
|
}
|
||||||
return DoneResult::Success;
|
return DoneResult::Success;
|
||||||
}
|
}
|
||||||
@@ -890,42 +869,41 @@ static ExecutableItem pidRecipe(RunnerStorage *storage)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidRunnerWorker::~AndroidRunnerWorker()
|
void RunnerInterface::setStarted(const Utils::Port &debugServerPort, const QUrl &qmlServer,
|
||||||
|
qint64 pid)
|
||||||
{
|
{
|
||||||
if (m_storage->m_processPID != -1)
|
emit started(debugServerPort, qmlServer, pid);
|
||||||
TaskTree::runBlocking(Group { forceStopRecipe(m_storage.get()), postDoneRecipe(m_storage.get()) });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidRunnerWorker::asyncStart()
|
ExecutableItem runnerRecipe(const Storage<RunnerInterface> &glueStorage)
|
||||||
{
|
{
|
||||||
// TODO: Instead of asyncStop recipe, add a barrier storage.
|
const Storage<RunnerStorage> storage;
|
||||||
const Group recipe {
|
|
||||||
|
const auto onSetup = [glueStorage, storage] {
|
||||||
|
setupStorage(storage.activeStorage(), glueStorage.activeStorage());
|
||||||
|
};
|
||||||
|
|
||||||
|
return Group {
|
||||||
finishAllAndSuccess,
|
finishAllAndSuccess,
|
||||||
|
storage,
|
||||||
|
onGroupSetup(onSetup),
|
||||||
Group {
|
Group {
|
||||||
forceStopRecipe(m_storage.get()),
|
forceStopRecipe(storage),
|
||||||
Group {
|
Group {
|
||||||
parallel,
|
parallel,
|
||||||
stopOnSuccessOrError,
|
stopOnSuccessOrError,
|
||||||
logcatRecipe(m_storage.get()),
|
logcatRecipe(storage),
|
||||||
Group {
|
Group {
|
||||||
preStartRecipe(m_storage.get()),
|
preStartRecipe(storage),
|
||||||
pidRecipe(m_storage.get())
|
pidRecipe(storage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.withCancel([storage = m_storage.get()] {
|
}.withCancel([glueStorage] {
|
||||||
return std::make_pair(storage, &RunnerStorage::cancel);
|
return std::make_pair(glueStorage.activeStorage(), &RunnerInterface::canceled);
|
||||||
}),
|
}),
|
||||||
forceStopRecipe(m_storage.get()),
|
forceStopRecipe(storage),
|
||||||
postDoneRecipe(m_storage.get())
|
postDoneRecipe(storage)
|
||||||
};
|
};
|
||||||
m_taskTreeRunner.start(recipe);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidRunnerWorker::asyncStop()
|
|
||||||
{
|
|
||||||
emit cancel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Android::Internal
|
} // namespace Android::Internal
|
||||||
|
|
||||||
#include "androidrunnerworker.moc"
|
|
||||||
|
@@ -8,34 +8,52 @@
|
|||||||
namespace ProjectExplorer { class RunControl; }
|
namespace ProjectExplorer { class RunControl; }
|
||||||
namespace Utils { class Port; }
|
namespace Utils { class Port; }
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QUrl;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Android::Internal {
|
namespace Android::Internal {
|
||||||
|
|
||||||
class RunnerStorage;
|
class RunnerInterface : public QObject
|
||||||
|
|
||||||
class AndroidRunnerWorker : public QObject
|
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AndroidRunnerWorker(ProjectExplorer::RunControl *runControl, const QString &deviceSerialNumber,
|
// Gui init setters
|
||||||
int apiLevel);
|
void setRunControl(ProjectExplorer::RunControl *runControl) { m_runControl = runControl; }
|
||||||
~AndroidRunnerWorker() override;
|
void setDeviceSerialNumber(const QString &deviceSerialNumber) { m_deviceSerialNumber = deviceSerialNumber; }
|
||||||
|
void setApiLevel(int apiLevel) { m_apiLevel = apiLevel; }
|
||||||
|
|
||||||
void asyncStart();
|
// business logic init getters
|
||||||
void asyncStop();
|
ProjectExplorer::RunControl *runControl() const { return m_runControl; }
|
||||||
|
QString deviceSerialNumber() const { return m_deviceSerialNumber; }
|
||||||
|
int apiLevel() const { return m_apiLevel; }
|
||||||
|
|
||||||
|
// GUI -> business logic
|
||||||
|
void cancel() { emit canceled(); }
|
||||||
|
|
||||||
|
// business logic -> GUI
|
||||||
|
void setStarted(const Utils::Port &debugServerPort, const QUrl &qmlServer, qint64 pid);
|
||||||
|
void setFinished(const QString &errorMessage) { emit finished(errorMessage); }
|
||||||
|
void addStdOut(const QString &data) { emit stdOut(data); }
|
||||||
|
void addStdErr(const QString &data) { emit stdErr(data); }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void remoteProcessStarted(const Utils::Port &debugServerPort, const QUrl &qmlServer, qint64 pid);
|
// GUI -> business logic
|
||||||
void remoteProcessFinished(const QString &errString = QString());
|
void canceled();
|
||||||
|
|
||||||
void remoteOutput(const QString &output);
|
// business logic -> GUI
|
||||||
void remoteErrorOutput(const QString &output);
|
void started(const Utils::Port &debugServerPort, const QUrl &qmlServer, qint64 pid);
|
||||||
|
void finished(const QString &errorMessage);
|
||||||
void cancel();
|
void stdOut(const QString &data);
|
||||||
|
void stdErr(const QString &data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<RunnerStorage> m_storage;
|
ProjectExplorer::RunControl *m_runControl = nullptr;
|
||||||
Tasking::TaskTreeRunner m_taskTreeRunner;
|
QString m_deviceSerialNumber;
|
||||||
|
int m_apiLevel = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Tasking::ExecutableItem runnerRecipe(const Tasking::Storage<RunnerInterface> &storage);
|
||||||
|
|
||||||
} // namespace Android::Internal
|
} // namespace Android::Internal
|
||||||
|
Reference in New Issue
Block a user