aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarek Kobus <[email protected]>2025-01-24 13:48:53 +0100
committerEike Ziller <[email protected]>2025-01-27 13:41:07 +0000
commitada52f62231fe31dff5236441dc0d5f2b4325448 (patch)
tree14bef2d4e99cf0dd7457866d2387c39671a27572
parentbbb36635edd7191bc533af632bcaa30d699157b3 (diff)
iOS: Fix QML Profiling on devices with iOS <= 16
Re-implement IosDevice::portsGatheringRecipe(), which tried to run netstat on the device. We don't know the used ports on device, the old code used to just count up from 30000. Just do not report any used ports for now. The port on the device is mapped to a local port, to which the QML Profiler actually has to connect. That is reported by iostool after starting the app, so we need to adapt the runControl's qmlChannel correspondingly when the correct port gets reported. For the debug run worker we have to manually request the same logic for QML debugging, with runControl->requestQmlChannel() if QML debugging is enabled. We cannot use the base DebuggerRunTool::setupPortsGatherer(), because that also requests that for the "debugChannel", and doing that changes the whole logic how the DebuggerRunTool works, breaking debugging in general on iOS. Fixes: QTCREATORBUG-32403 Change-Id: I9574703e771e154fcfa7754706ac9871f3e61251 Reviewed-by: Jarek Kobus <[email protected]>
-rw-r--r--src/plugins/ios/iosdevice.cpp38
-rw-r--r--src/plugins/ios/iosdevice.h8
-rw-r--r--src/plugins/ios/iosrunner.cpp35
3 files changed, 48 insertions, 33 deletions
diff --git a/src/plugins/ios/iosdevice.cpp b/src/plugins/ios/iosdevice.cpp
index 76b7c4911e3..61a99fd9b95 100644
--- a/src/plugins/ios/iosdevice.cpp
+++ b/src/plugins/ios/iosdevice.cpp
@@ -22,6 +22,7 @@
#include <utils/portlist.h>
#include <utils/qtcprocess.h>
#include <utils/shutdownguard.h>
+#include <utils/url.h>
#include <solutions/tasking/tasktree.h>
@@ -48,6 +49,7 @@
#include <exception>
using namespace ProjectExplorer;
+using namespace Tasking;
using namespace Utils;
namespace {
@@ -105,7 +107,6 @@ public:
};
IosDevice::IosDevice(CtorHelper)
- : m_lastPort(Constants::IOS_DEVICE_PORT_START)
{
setType(Constants::IOS_DEVICE_TYPE);
setDefaultDisplayName(IosDevice::name());
@@ -157,6 +158,12 @@ void IosDevice::fromMap(const Store &map)
for (auto i = vMap.cbegin(), end = vMap.cend(); i != end; ++i)
m_extraInfo.insert(stringFromKey(i.key()), i.value().toString());
m_handler = Handler(map.value(kHandler).toInt());
+ // TODO IDevice::fromMap overrides the port list that we set in the constructor
+ // this shouldn't happen
+ Utils::PortList ports;
+ ports.addRange(
+ Utils::Port(Constants::IOS_DEVICE_PORT_START), Utils::Port(Constants::IOS_DEVICE_PORT_END));
+ setFreePorts(ports);
}
void IosDevice::toMap(Store &map) const
@@ -170,6 +177,25 @@ void IosDevice::toMap(Store &map) const
map.insert(kHandler, int(m_handler));
}
+ExecutableItem IosDevice::portsGatheringRecipe(
+ [[maybe_unused]] const Storage<PortsOutputData> &output) const
+{
+ // We don't really know how to get all used ports on the device.
+ // The code in <= 15.0 cycled through the list (30001 for the first run,
+ // 30002 for the second run etc)
+ // I guess that would be needed if we could run/profile multiple applications on
+ // the device simultaneously, we cannot
+ return Group{nullItem};
+}
+
+QUrl IosDevice::toolControlChannel(const ControlChannelHint &) const
+{
+ QUrl url;
+ url.setScheme(Utils::urlTcpScheme());
+ url.setHost("localhost");
+ return url;
+}
+
QString IosDevice::deviceName() const
{
return m_extraInfo.value(kDeviceName);
@@ -205,14 +231,6 @@ QString IosDevice::cpuArchitecture() const
return m_extraInfo.value(kCpuArchitecture);
}
-Utils::Port IosDevice::nextPort() const
-{
- // use qrand instead?
- if (++m_lastPort >= Constants::IOS_DEVICE_PORT_END)
- m_lastPort = Constants::IOS_DEVICE_PORT_START;
- return Utils::Port(m_lastPort);
-}
-
IosDevice::Handler IosDevice::handler() const
{
return m_handler;
@@ -290,8 +308,6 @@ void IosDeviceManager::deviceDisconnected(const QString &uid)
void IosDeviceManager::updateInfo(const QString &devId)
{
- using namespace Tasking;
-
const auto getDeviceCtlVersion = ProcessTask(
[](Process &process) {
process.setCommand({FilePath::fromString("/usr/bin/xcrun"), {"devicectl", "--version"}});
diff --git a/src/plugins/ios/iosdevice.h b/src/plugins/ios/iosdevice.h
index edaac2d4164..5e4ecdc61ac 100644
--- a/src/plugins/ios/iosdevice.h
+++ b/src/plugins/ios/iosdevice.h
@@ -41,15 +41,18 @@ public:
QString osVersion() const;
QString productType() const;
QString cpuArchitecture() const;
- Utils::Port nextPort() const;
Handler handler() const;
static QString name();
-protected:
+private:
void fromMap(const Utils::Store &map) final;
void toMap(Utils::Store &map) const final;
+ Tasking::ExecutableItem portsGatheringRecipe(
+ const Tasking::Storage<Utils::PortsOutputData> &output) const override;
+ QUrl toolControlChannel(const ControlChannelHint &) const override;
+
friend class IosDeviceFactory;
friend class Ios::Internal::IosDeviceManager;
IosDevice();
@@ -61,7 +64,6 @@ protected:
Dict m_extraInfo;
Handler m_handler = Handler::IosTool;
bool m_ignoreDevice = false;
- mutable quint16 m_lastPort;
};
class IosDeviceManager : public QObject
diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp
index 9cb34798929..61f4a52d14d 100644
--- a/src/plugins/ios/iosrunner.cpp
+++ b/src/plugins/ios/iosrunner.cpp
@@ -528,7 +528,6 @@ public:
void start() override;
void stop() final;
- Port qmlServerPort() const;
Port gdbServerPort() const;
qint64 pid() const;
bool isAppRunning() const;
@@ -634,13 +633,8 @@ void IosRunner::start()
return;
}
if (m_device->type() == Ios::Constants::IOS_DEVICE_TYPE) {
- IosDevice::ConstPtr iosDevice = std::dynamic_pointer_cast<const IosDevice>(m_device);
- if (!m_device) {
- reportFailure();
- return;
- }
if (m_qmlDebugServices != NoQmlDebugServices)
- m_qmlServerPort = iosDevice->nextPort();
+ m_qmlServerPort = Port(runControl()->qmlChannel().port());
} else {
IosSimulator::ConstPtr sim = std::dynamic_pointer_cast<const IosSimulator>(m_device);
if (!sim) {
@@ -696,6 +690,13 @@ void IosRunner::handleGotServerPorts(IosToolHandler *handler, const FilePath &bu
m_gdbServerPort = gdbPort;
m_qmlServerPort = qmlPort;
+ // The run control so far knows about the port on the device side,
+ // but the QML Profiler has to actually connect to a corresponding
+ // local port. That port is reported here, so we need to adapt the runControl's
+ // "qmlChannel", so the QmlProfilerRunner uses the right port.
+ QUrl qmlChannel = runControl()->qmlChannel();
+ qmlChannel.setPort(qmlPort.number());
+ runControl()->setQmlChannel(qmlChannel);
bool prerequisiteOk = false;
if (cppDebug() && qmlDebug())
@@ -813,11 +814,6 @@ Port IosRunner::gdbServerPort() const
return m_gdbServerPort;
}
-Port IosRunner::qmlServerPort() const
-{
- return m_qmlServerPort;
-}
-
//
// IosQmlProfilerSupport
//
@@ -849,12 +845,7 @@ IosQmlProfilerSupport::IosQmlProfilerSupport(RunControl *runControl)
void IosQmlProfilerSupport::start()
{
- QTcpServer server;
- const bool isListening = server.listen(QHostAddress::LocalHost)
- || server.listen(QHostAddress::LocalHostIPv6);
- QTC_ASSERT(isListening, return);
-
- const Port qmlPort = m_runner->qmlServerPort();
+ const Port qmlPort = Port(runControl()->qmlChannel().port());
if (qmlPort.isValid())
reportStarted();
else
@@ -909,6 +900,12 @@ IosDebugSupport::IosDebugSupport(RunControl *runControl)
IosDevice::ConstPtr dev = std::dynamic_pointer_cast<const IosDevice>(runControl->device());
DebuggerRunParameters &rp = runParameters();
+ // TODO cannot use setupPortsGatherer() from DebuggerRunTool, because that also requests
+ // the "debugChannel", which then results in runControl trying to retrieve ports&URL for that
+ // via IDevice, which doesn't really work with the iOS setup, and also completely changes
+ // how the DebuggerRunTool works, breaking debugging on iOS <= 16 devices.
+ if (rp.isQmlDebugging())
+ runControl->requestQmlChannel();
if (dev->type() == Ios::Constants::IOS_SIMULATOR_TYPE
|| dev->handler() == IosDevice::Handler::IosTool) {
@@ -978,7 +975,7 @@ void IosDebugSupport::start()
}
const Port gdbServerPort = m_iosRunner->gdbServerPort();
- const Port qmlServerPort = m_iosRunner->qmlServerPort();
+ const Port qmlServerPort = Port(runControl()->qmlChannel().port());
rp.setAttachPid(m_iosRunner->pid());
const bool cppDebug = rp.isCppDebugging();