2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
|
|
|
|
|
// Copyright (C) 2016 The Qt Company Ltd.
|
2022-12-21 10:12:09 +01:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
2012-04-18 20:30:57 +03:00
|
|
|
|
2024-07-11 17:37:47 +02:00
|
|
|
#include "androidrunner.h"
|
|
|
|
|
|
2021-08-22 01:51:57 +03:00
|
|
|
#include "androidavdmanager.h"
|
|
|
|
|
#include "androiddevice.h"
|
2012-04-24 15:49:09 +02:00
|
|
|
#include "androidmanager.h"
|
2018-03-17 09:31:56 +02:00
|
|
|
#include "androidrunnerworker.h"
|
2022-10-06 17:53:35 +02:00
|
|
|
#include "androidtr.h"
|
2012-04-24 15:49:09 +02:00
|
|
|
|
2016-06-08 16:57:32 +02:00
|
|
|
#include <projectexplorer/projectexplorersettings.h>
|
2012-04-24 15:49:09 +02:00
|
|
|
#include <projectexplorer/target.h>
|
2023-08-11 11:23:12 +02:00
|
|
|
#include <qtsupport/qtkitaspect.h>
|
2017-09-29 12:41:53 +02:00
|
|
|
#include <utils/url.h>
|
2012-04-18 20:30:57 +03:00
|
|
|
|
2020-04-16 07:13:00 +02:00
|
|
|
#include <QHostAddress>
|
2018-06-18 11:49:14 +02:00
|
|
|
#include <QLoggingCategory>
|
|
|
|
|
|
|
|
|
|
namespace {
|
2020-01-15 14:39:23 +01:00
|
|
|
static Q_LOGGING_CATEGORY(androidRunnerLog, "qtc.android.run.androidrunner", QtWarningMsg)
|
2018-06-18 11:49:14 +02:00
|
|
|
}
|
|
|
|
|
|
2016-06-08 16:57:32 +02:00
|
|
|
using namespace ProjectExplorer;
|
2024-07-11 17:37:47 +02:00
|
|
|
using namespace Tasking;
|
2017-05-19 14:40:49 +02:00
|
|
|
using namespace Utils;
|
2016-06-08 16:57:32 +02:00
|
|
|
|
2024-07-11 17:37:47 +02:00
|
|
|
namespace Android::Internal {
|
2012-04-18 20:30:57 +03:00
|
|
|
|
2024-07-26 14:40:24 +02:00
|
|
|
AndroidRunner::AndroidRunner(RunControl *runControl)
|
|
|
|
|
: RunWorker(runControl)
|
|
|
|
|
, m_target(runControl->target())
|
2016-08-05 15:40:33 +02:00
|
|
|
{
|
2018-08-21 08:28:27 +02:00
|
|
|
setId("AndroidRunner");
|
2016-08-05 15:40:33 +02:00
|
|
|
static const int metaTypes[] = {
|
2024-04-23 23:48:38 +02:00
|
|
|
qRegisterMetaType<QList<QStringList>>("QList<QStringList>"),
|
2018-05-18 14:37:11 +02:00
|
|
|
qRegisterMetaType<Utils::Port>("Utils::Port"),
|
|
|
|
|
qRegisterMetaType<AndroidDeviceInfo>("Android::AndroidDeviceInfo")
|
2016-08-05 15:40:33 +02:00
|
|
|
};
|
2019-07-23 10:58:00 +02:00
|
|
|
Q_UNUSED(metaTypes)
|
2016-08-05 15:40:33 +02:00
|
|
|
|
2024-07-26 14:52:47 +02:00
|
|
|
m_worker = new AndroidRunnerWorker(this);
|
2016-08-05 15:40:33 +02:00
|
|
|
m_worker->moveToThread(&m_thread);
|
2024-07-11 15:52:28 +02:00
|
|
|
QObject::connect(&m_thread, &QThread::finished, m_worker, &QObject::deleteLater);
|
2016-08-05 15:40:33 +02:00
|
|
|
|
2024-07-11 15:52:28 +02:00
|
|
|
connect(this, &AndroidRunner::asyncStart, m_worker, &AndroidRunnerWorker::asyncStart);
|
|
|
|
|
connect(this, &AndroidRunner::asyncStop, m_worker, &AndroidRunnerWorker::asyncStop);
|
2018-05-07 17:13:52 +02:00
|
|
|
connect(this, &AndroidRunner::androidDeviceInfoChanged,
|
2024-07-11 15:52:28 +02:00
|
|
|
m_worker, &AndroidRunnerWorker::setAndroidDeviceInfo);
|
|
|
|
|
|
|
|
|
|
connect(m_worker, &AndroidRunnerWorker::remoteProcessStarted,
|
2017-05-19 14:40:49 +02:00
|
|
|
this, &AndroidRunner::handleRemoteProcessStarted);
|
2024-07-11 15:52:28 +02:00
|
|
|
connect(m_worker, &AndroidRunnerWorker::remoteProcessFinished,
|
2017-05-19 14:40:49 +02:00
|
|
|
this, &AndroidRunner::handleRemoteProcessFinished);
|
2024-07-11 15:52:28 +02:00
|
|
|
connect(m_worker, &AndroidRunnerWorker::remoteOutput, this, &AndroidRunner::remoteOutput);
|
|
|
|
|
connect(m_worker, &AndroidRunnerWorker::remoteErrorOutput,
|
2016-08-05 15:40:33 +02:00
|
|
|
this, &AndroidRunner::remoteErrorOutput);
|
|
|
|
|
|
2017-06-14 14:59:23 +02:00
|
|
|
connect(&m_outputParser, &QmlDebug::QmlOutputParser::waitingForConnectionOnPort,
|
|
|
|
|
this, &AndroidRunner::qmlServerPortReady);
|
|
|
|
|
|
2016-08-05 15:40:33 +02:00
|
|
|
m_thread.start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AndroidRunner::~AndroidRunner()
|
|
|
|
|
{
|
|
|
|
|
m_thread.quit();
|
|
|
|
|
m_thread.wait();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidRunner::start()
|
|
|
|
|
{
|
2024-07-11 17:37:47 +02:00
|
|
|
if (!projectExplorerSettings().deployBeforeRun && m_target && m_target->project()) {
|
2018-06-18 11:49:14 +02:00
|
|
|
qCDebug(androidRunnerLog) << "Run without deployment";
|
2016-08-05 15:40:33 +02:00
|
|
|
|
2024-07-11 17:37:47 +02:00
|
|
|
const IDevice::ConstPtr device = DeviceKitAspect::device(m_target->kit());
|
|
|
|
|
AndroidDeviceInfo info = AndroidDevice::androidDeviceInfoFromIDevice(device.get());
|
|
|
|
|
AndroidManager::setDeviceSerialNumber(m_target, info.serialNumber);
|
|
|
|
|
emit androidDeviceInfoChanged(info);
|
|
|
|
|
|
|
|
|
|
if (!info.avdName.isEmpty()) {
|
|
|
|
|
const Storage<QString> serialNumberStorage;
|
|
|
|
|
|
|
|
|
|
const Group recipe {
|
|
|
|
|
serialNumberStorage,
|
|
|
|
|
AndroidAvdManager::startAvdRecipe(info.avdName, serialNumberStorage)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
m_startAvdRunner.start(recipe, {}, [this](DoneWith result) {
|
|
|
|
|
if (result == DoneWith::Success)
|
|
|
|
|
emit asyncStart();
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-06-08 14:57:09 +02:00
|
|
|
emit asyncStart();
|
2016-08-05 15:40:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidRunner::stop()
|
|
|
|
|
{
|
2024-07-11 17:37:47 +02:00
|
|
|
if (m_startAvdRunner.isRunning()) {
|
|
|
|
|
m_startAvdRunner.reset();
|
2024-07-26 14:52:47 +02:00
|
|
|
appendMessage("\n\n" + Tr::tr("\"%1\" terminated.").arg(AndroidManager::packageName(m_target)),
|
2021-01-13 15:00:15 +01:00
|
|
|
Utils::NormalMessageFormat);
|
2016-08-05 15:40:33 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2017-06-08 14:57:09 +02:00
|
|
|
emit asyncStop();
|
2016-08-05 15:40:33 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-14 14:59:23 +02:00
|
|
|
void AndroidRunner::qmlServerPortReady(Port port)
|
|
|
|
|
{
|
|
|
|
|
// FIXME: Note that the passed is nonsense, as the port is on the
|
|
|
|
|
// device side. It only happens to work since we redirect
|
|
|
|
|
// host port n to target port n via adb.
|
|
|
|
|
QUrl serverUrl;
|
2018-07-05 08:13:08 +02:00
|
|
|
serverUrl.setHost(QHostAddress(QHostAddress::LocalHost).toString());
|
2017-06-14 14:59:23 +02:00
|
|
|
serverUrl.setPort(port.number());
|
2017-10-13 10:02:41 +02:00
|
|
|
serverUrl.setScheme(urlTcpScheme());
|
2018-07-17 13:58:50 +02:00
|
|
|
qCDebug(androidRunnerLog) << "Qml Server port ready"<< serverUrl;
|
2017-06-14 14:59:23 +02:00
|
|
|
emit qmlServerReady(serverUrl);
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-19 14:40:49 +02:00
|
|
|
void AndroidRunner::remoteOutput(const QString &output)
|
|
|
|
|
{
|
2020-03-17 15:18:06 +01:00
|
|
|
appendMessage(output, Utils::StdOutFormat);
|
2017-06-14 14:59:23 +02:00
|
|
|
m_outputParser.processOutput(output);
|
2017-05-19 14:40:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidRunner::remoteErrorOutput(const QString &output)
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2020-03-17 15:18:06 +01:00
|
|
|
appendMessage(output, Utils::StdErrFormat);
|
2017-06-14 14:59:23 +02:00
|
|
|
m_outputParser.processOutput(output);
|
2017-05-19 14:40:49 +02:00
|
|
|
}
|
|
|
|
|
|
2020-04-15 04:33:06 +02:00
|
|
|
void AndroidRunner::handleRemoteProcessStarted(Utils::Port debugServerPort,
|
2019-12-02 13:56:56 +02:00
|
|
|
const QUrl &qmlServer, qint64 pid)
|
2017-05-19 14:40:49 +02:00
|
|
|
{
|
|
|
|
|
m_pid = ProcessHandle(pid);
|
2020-04-15 04:33:06 +02:00
|
|
|
m_debugServerPort = debugServerPort;
|
2017-08-18 12:23:42 +02:00
|
|
|
m_qmlServer = qmlServer;
|
2017-05-19 14:40:49 +02:00
|
|
|
reportStarted();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidRunner::handleRemoteProcessFinished(const QString &errString)
|
|
|
|
|
{
|
2021-01-13 15:00:15 +01:00
|
|
|
appendMessage(errString, Utils::NormalMessageFormat);
|
2017-06-14 14:59:23 +02:00
|
|
|
if (runControl()->isRunning())
|
|
|
|
|
runControl()->initiateStop();
|
2017-05-19 14:40:49 +02:00
|
|
|
reportStopped();
|
2016-01-29 14:05:00 +02:00
|
|
|
}
|
|
|
|
|
|
2024-07-11 17:37:47 +02:00
|
|
|
} // namespace Android::Internal
|