forked from qt-creator/qt-creator
Android: Run pid watcher in the main thread
Change-Id: Ia320827ed97caa3dff0611a13c52e648c9d8a79a Reviewed-by: hjk <hjk@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -14,30 +14,27 @@
|
|||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
#include <projectexplorer/buildsystem.h>
|
#include <projectexplorer/buildsystem.h>
|
||||||
#include <projectexplorer/devicesupport/devicemanager.h>
|
|
||||||
#include <projectexplorer/environmentaspect.h>
|
#include <projectexplorer/environmentaspect.h>
|
||||||
#include <projectexplorer/kit.h>
|
|
||||||
#include <projectexplorer/project.h>
|
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <projectexplorer/runcontrol.h>
|
#include <projectexplorer/runcontrol.h>
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
|
|
||||||
|
#include <solutions/tasking/tasktreerunner.h>
|
||||||
|
|
||||||
#include <qmlprojectmanager/qmlprojectconstants.h>
|
#include <qmlprojectmanager/qmlprojectconstants.h>
|
||||||
|
|
||||||
#include <qtsupport/baseqtversion.h>
|
|
||||||
#include <qtsupport/qtkitaspect.h>
|
#include <qtsupport/qtkitaspect.h>
|
||||||
|
|
||||||
#include <utils/async.h>
|
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDeadlineTimer>
|
|
||||||
#include <QFutureWatcher>
|
|
||||||
#include <QThread>
|
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
|
using namespace Tasking;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
namespace Android::Internal {
|
namespace Android::Internal {
|
||||||
|
|
||||||
#define APP_ID "io.qt.qtdesignviewer"
|
#define APP_ID "io.qt.qtdesignviewer"
|
||||||
@@ -82,7 +79,6 @@ class AndroidQmlPreviewWorker : public RunWorker
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
AndroidQmlPreviewWorker(RunControl *runControl);
|
AndroidQmlPreviewWorker(RunControl *runControl);
|
||||||
~AndroidQmlPreviewWorker();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void previewPidChanged();
|
void previewPidChanged();
|
||||||
@@ -96,10 +92,9 @@ private:
|
|||||||
bool preparePreviewArtefacts();
|
bool preparePreviewArtefacts();
|
||||||
bool uploadPreviewArtefacts();
|
bool uploadPreviewArtefacts();
|
||||||
|
|
||||||
|
CommandLine adbCommand(const QStringList &arguments) const;
|
||||||
SdkToolResult runAdbCommand(const QStringList &arguments) const;
|
SdkToolResult runAdbCommand(const QStringList &arguments) const;
|
||||||
SdkToolResult runAdbShellCommand(const QStringList &arguments) const;
|
SdkToolResult runAdbShellCommand(const QStringList &arguments) const;
|
||||||
int pidofPreview() const;
|
|
||||||
bool isPreviewRunning(int lastKnownPid = -1) const;
|
|
||||||
|
|
||||||
void startPidWatcher();
|
void startPidWatcher();
|
||||||
void startLogcat();
|
void startLogcat();
|
||||||
@@ -115,7 +110,7 @@ private:
|
|||||||
QString m_serialNumber;
|
QString m_serialNumber;
|
||||||
QStringList m_avdAbis;
|
QStringList m_avdAbis;
|
||||||
int m_viewerPid = -1;
|
int m_viewerPid = -1;
|
||||||
QFutureWatcher<void> m_pidFutureWatcher;
|
TaskTreeRunner m_pidRunner;
|
||||||
Utils::Process m_logcatProcess;
|
Utils::Process m_logcatProcess;
|
||||||
QString m_logcatStartTimeStamp;
|
QString m_logcatStartTimeStamp;
|
||||||
UploadInfo m_uploadInfo;
|
UploadInfo m_uploadInfo;
|
||||||
@@ -133,6 +128,16 @@ FilePath AndroidQmlPreviewWorker::designViewerApkPath(const QString &abi) const
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CommandLine AndroidQmlPreviewWorker::adbCommand(const QStringList &arguments) const
|
||||||
|
{
|
||||||
|
CommandLine cmd{androidConfig().adbToolPath()};
|
||||||
|
if (!m_serialNumber.isEmpty())
|
||||||
|
cmd.addArgs(AndroidDeviceInfo::adbSelector(m_serialNumber));
|
||||||
|
cmd.addArg("shell");
|
||||||
|
cmd.addArgs(arguments);
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
SdkToolResult AndroidQmlPreviewWorker::runAdbCommand(const QStringList &arguments) const
|
SdkToolResult AndroidQmlPreviewWorker::runAdbCommand(const QStringList &arguments) const
|
||||||
{
|
{
|
||||||
QStringList args;
|
QStringList args;
|
||||||
@@ -147,44 +152,49 @@ SdkToolResult AndroidQmlPreviewWorker::runAdbShellCommand(const QStringList &arg
|
|||||||
return runAdbCommand(QStringList() << "shell" << arguments);
|
return runAdbCommand(QStringList() << "shell" << arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
int AndroidQmlPreviewWorker::pidofPreview() const
|
|
||||||
{
|
|
||||||
const QStringList command{"pidof", apkInfo()->appId};
|
|
||||||
const SdkToolResult res = runAdbShellCommand(command);
|
|
||||||
return res.success() ? res.stdOut().toInt() : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AndroidQmlPreviewWorker::isPreviewRunning(int lastKnownPid) const
|
|
||||||
{
|
|
||||||
const int pid = pidofPreview();
|
|
||||||
return (lastKnownPid > 1) ? lastKnownPid == pid : pid > 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidQmlPreviewWorker::startPidWatcher()
|
void AndroidQmlPreviewWorker::startPidWatcher()
|
||||||
{
|
{
|
||||||
m_pidFutureWatcher.setFuture(Utils::asyncRun([this] {
|
const LoopUntil pidIterator([this](int) { return m_viewerPid <= 0; });
|
||||||
// wait for started
|
const LoopUntil alivePidIterator([this](int) { return m_viewerPid > 0; });
|
||||||
const int sleepTimeMs = 2000;
|
|
||||||
QDeadlineTimer deadline(20000);
|
|
||||||
while (!m_pidFutureWatcher.isCanceled() && !deadline.hasExpired()) {
|
|
||||||
if (m_viewerPid == -1) {
|
|
||||||
m_viewerPid = pidofPreview();
|
|
||||||
if (m_viewerPid > 0) {
|
|
||||||
emit previewPidChanged();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QThread::msleep(sleepTimeMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!m_pidFutureWatcher.isCanceled()) {
|
const auto onPidSetup = [this](Process &process) {
|
||||||
if (!isPreviewRunning(m_viewerPid)) {
|
process.setCommand(adbCommand({"pidof", apkInfo()->appId}));
|
||||||
stop();
|
};
|
||||||
break;
|
const auto onPidDone = [this](const Process &process) {
|
||||||
}
|
bool ok = false;
|
||||||
QThread::msleep(sleepTimeMs);
|
const int pid = process.cleanedStdOut().trimmed().toInt(&ok);
|
||||||
|
if (ok && pid > 0) {
|
||||||
|
m_viewerPid = pid;
|
||||||
|
// TODO: make a continuation task (logcat)
|
||||||
|
emit previewPidChanged();
|
||||||
}
|
}
|
||||||
}));
|
};
|
||||||
|
|
||||||
|
const auto onAlivePidDone = [this](const Process &process) {
|
||||||
|
bool ok = false;
|
||||||
|
const int pid = process.cleanedStdOut().trimmed().toInt(&ok);
|
||||||
|
if (!ok || pid != m_viewerPid) {
|
||||||
|
m_viewerPid = -1;
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const TimeoutTask timeout([](std::chrono::milliseconds &timeout) { timeout = 2s; });
|
||||||
|
|
||||||
|
const Group root {
|
||||||
|
Group {
|
||||||
|
pidIterator,
|
||||||
|
ProcessTask(onPidSetup, onPidDone, CallDoneIf::Success),
|
||||||
|
timeout
|
||||||
|
}.withTimeout(20s),
|
||||||
|
Group {
|
||||||
|
alivePidIterator,
|
||||||
|
ProcessTask(onPidSetup, onAlivePidDone),
|
||||||
|
timeout
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
m_pidRunner.start(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidQmlPreviewWorker::startLogcat()
|
void AndroidQmlPreviewWorker::startLogcat()
|
||||||
@@ -220,7 +230,7 @@ AndroidQmlPreviewWorker::AndroidQmlPreviewWorker(RunControl *runControl)
|
|||||||
m_rc(runControl)
|
m_rc(runControl)
|
||||||
{
|
{
|
||||||
connect(this, &RunWorker::started, this, &AndroidQmlPreviewWorker::startPidWatcher);
|
connect(this, &RunWorker::started, this, &AndroidQmlPreviewWorker::startPidWatcher);
|
||||||
connect(this, &RunWorker::stopped, &m_pidFutureWatcher, &QFutureWatcher<void>::cancel);
|
connect(this, &RunWorker::stopped, &m_pidRunner, &TaskTreeRunner::reset);
|
||||||
connect(this, &AndroidQmlPreviewWorker::previewPidChanged,
|
connect(this, &AndroidQmlPreviewWorker::previewPidChanged,
|
||||||
this, &AndroidQmlPreviewWorker::startLogcat);
|
this, &AndroidQmlPreviewWorker::startLogcat);
|
||||||
|
|
||||||
@@ -230,12 +240,6 @@ AndroidQmlPreviewWorker::AndroidQmlPreviewWorker(RunControl *runControl)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidQmlPreviewWorker::~AndroidQmlPreviewWorker()
|
|
||||||
{
|
|
||||||
m_pidFutureWatcher.cancel();
|
|
||||||
m_pidFutureWatcher.waitForFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidQmlPreviewWorker::start()
|
void AndroidQmlPreviewWorker::start()
|
||||||
{
|
{
|
||||||
const SdkToolResult dateResult = runAdbCommand({"shell", "date", "+%s"});
|
const SdkToolResult dateResult = runAdbCommand({"shell", "date", "+%s"});
|
||||||
@@ -254,7 +258,7 @@ void AndroidQmlPreviewWorker::start()
|
|||||||
|
|
||||||
void AndroidQmlPreviewWorker::stop()
|
void AndroidQmlPreviewWorker::stop()
|
||||||
{
|
{
|
||||||
if (!isPreviewRunning(m_viewerPid) || stopPreviewApp())
|
if (m_viewerPid <= 0 || stopPreviewApp())
|
||||||
appendMessage(Tr::tr("%1 has been stopped.").arg(apkInfo()->name), NormalMessageFormat);
|
appendMessage(Tr::tr("%1 has been stopped.").arg(apkInfo()->name), NormalMessageFormat);
|
||||||
m_viewerPid = -1;
|
m_viewerPid = -1;
|
||||||
reportStopped();
|
reportStopped();
|
||||||
|
|||||||
Reference in New Issue
Block a user