summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAssam Boudjelthia <assam.boudjelthia@qt.io>2021-10-29 18:19:54 +0300
committerAssam Boudjelthia <assam.boudjelthia@qt.io>2022-02-22 21:21:53 +0000
commitc43ba1ae329937db62c4824311fe017b68b6033f (patch)
tree32b867844606e990c2b37518b648a8de1a17c6ea
parentd8b5d2b7a552547d0c5d4d1ba904fbde76a319a2 (diff)
downloadqt-creator-c43ba1ae329937db62c4824311fe017b68b6033f.tar.gz
Monitor Android devices in non-polling method
Use ADB's track-devices command to watch for device events which would replace the current polling method with a timer. For AVDs, a QFileSystemWatcher is used to watch for changes in the AVDs home folder which would allow updating the AVDs only when a change is done like edition, deletion, start, stop, even from outside Qt Creator. This method would also make device updates faster, instead of unexpected waits due to timer use. Task-number: QTCREATORBUG-23991 Change-Id: I08a92252c99c02bc111e597d671f2350817458c7 Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
-rw-r--r--src/plugins/android/androidconfigurations.cpp43
-rw-r--r--src/plugins/android/androidconfigurations.h6
-rw-r--r--src/plugins/android/androiddevice.cpp284
-rw-r--r--src/plugins/android/androiddevice.h24
4 files changed, 212 insertions, 145 deletions
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
index 9de48da0ee..7400020bbb 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2022 The Qt Company Ltd.
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
** Contact: https://www.qt.io/licensing/
**
@@ -752,48 +753,6 @@ QString AndroidConfig::getAvdName(const QString &serialnumber)
return QString::fromLatin1(name).trimmed();
}
-static SdkToolResult emulatorNameAdbCommand(const QString &serialNumber)
-{
- QStringList args = AndroidDeviceInfo::adbSelector(serialNumber);
- args.append({"emu", "avd", "name"});
- return AndroidManager::runAdbCommand(args);
-}
-
-QString AndroidConfig::getRunningAvdsSerialNumber(const QString &name) const
-{
- for (const AndroidDeviceInfo &dev : connectedDevices()) {
- if (!dev.serialNumber.startsWith("emulator"))
- continue;
- SdkToolResult result = emulatorNameAdbCommand(dev.serialNumber);
- const QString stdOut = result.stdOut();
- if (stdOut.isEmpty())
- continue; // Not an avd
- const QStringList outputLines = stdOut.split('\n');
- if (outputLines.size() > 1 && outputLines.first() == name)
- return dev.serialNumber;
- }
-
- return {};
-}
-
-QStringList AndroidConfig::getRunningAvdsFromDevices(const QVector<AndroidDeviceInfo> &devs)
-{
- QStringList runningDevs;
- for (const AndroidDeviceInfo &dev : devs) {
- if (!dev.serialNumber.startsWith("emulator"))
- continue;
- SdkToolResult result = emulatorNameAdbCommand(dev.serialNumber);
- const QString stdOut = result.stdOut();
- if (stdOut.isEmpty())
- continue; // Not an avd
- const QStringList outputLines = stdOut.split('\n');
- if (outputLines.size() > 1)
- runningDevs.append(outputLines.first());
- }
-
- return runningDevs;
-}
-
AndroidConfig::OpenGl AndroidConfig::getOpenGLEnabled(const QString &emulator) const
{
QDir dir = QDir::home();
diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h
index 7492ae0f2a..5338845d0d 100644
--- a/src/plugins/android/androidconfigurations.h
+++ b/src/plugins/android/androidconfigurations.h
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2022 The Qt Company Ltd.
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
** Contact: https://www.qt.io/licensing/
**
@@ -176,15 +177,12 @@ public:
static Utils::FilePath getJdkPath();
static QStringList getAbis(const QString &device);
-
- QString getRunningAvdsSerialNumber(const QString &name) const;
- static QStringList getRunningAvdsFromDevices(const QVector<AndroidDeviceInfo> &devs);
+ static int getSDKVersion(const QString &device);
private:
static QString getDeviceProperty(const QString &device, const QString &property);
Utils::FilePath openJDKBinPath() const;
- static int getSDKVersion(const QString &device);
static QString getAvdName(const QString &serialnumber);
void parseDependenciesJson();
diff --git a/src/plugins/android/androiddevice.cpp b/src/plugins/android/androiddevice.cpp
index a14b985ad7..b7927d0aa8 100644
--- a/src/plugins/android/androiddevice.cpp
+++ b/src/plugins/android/androiddevice.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
** Contact: https://www.qt.io/licensing/
**
@@ -52,6 +52,9 @@
#include <QLoggingCategory>
#include <QMessageBox>
#include <QPushButton>
+#include <QTimer>
+
+#include <utils/qtcprocess.h>
using namespace ProjectExplorer;
@@ -59,9 +62,6 @@ namespace {
static Q_LOGGING_CATEGORY(androidDeviceLog, "qtc.android.androiddevice", QtWarningMsg)
}
-// interval for updating the list of connected Android devices and emulators
-constexpr int deviceUpdaterMsInterval = 30000;
-
namespace Android {
namespace Internal {
@@ -328,7 +328,7 @@ QString AndroidDevice::serialNumber() const
if (machineType() == Hardware)
return serialNumber;
- return AndroidConfigurations::currentConfig().getRunningAvdsSerialNumber(avdName());
+ return AndroidDeviceManager::instance()->getRunningAvdsSerialNumber(avdName());
}
QString AndroidDevice::avdName() const
@@ -419,36 +419,28 @@ QUrl AndroidDevice::toolControlChannel(const ControlChannelHint &) const
return url;
}
-void AndroidDeviceManager::updateDevicesList()
+void AndroidDeviceManager::updateAvdsList()
{
- // If a non-Android Kit is currently active, skip the device list update
- const Target *startupTarget = SessionManager::startupTarget();
- if (!startupTarget)
- return;
-
- const Kit *kit = startupTarget->kit();
- if (!kit)
- return;
-
- if (DeviceTypeKitAspect::deviceTypeId(kit) != Constants::ANDROID_DEVICE_TYPE)
- return;
-
- updateDevicesListOnce();
+ if (!m_avdsFutureWatcher.isRunning() && m_androidConfig.adbToolPath().exists())
+ m_avdsFutureWatcher.setFuture(m_avdManager.avdList());
}
-void AndroidDeviceManager::updateDevicesListOnce()
+IDevice::DeviceState AndroidDeviceManager::getDeviceState(const QString &serial,
+ IDevice::MachineType type) const
{
- if (!m_avdsFutureWatcher.isRunning() && m_androidConfig.adbToolPath().exists()) {
- m_avdsFutureWatcher.setFuture(m_avdManager.avdList());
- m_devicesFutureWatcher.setFuture(Utils::runAsync([this]() {
- return m_androidConfig.connectedDevices();
- }));
- }
+ const QStringList args = AndroidDeviceInfo::adbSelector(serial) << "shell" << "echo 1";
+ const SdkToolResult result = AndroidManager::runAdbCommand(args);
+ if (result.success())
+ return IDevice::DeviceReadyToUse;
+ else if (type == IDevice::Emulator || result.stdErr().contains("unauthorized"))
+ return IDevice::DeviceConnected;
+
+ return IDevice::DeviceDisconnected;
}
-void AndroidDeviceManager::updateDeviceState(const ProjectExplorer::IDevice::Ptr &device)
+void AndroidDeviceManager::updateDeviceState(const ProjectExplorer::IDevice::ConstPtr &device)
{
- const AndroidDevice *dev = static_cast<AndroidDevice *>(device.data());
+ const AndroidDevice *dev = static_cast<const AndroidDevice *>(device.data());
const QString serial = dev->serialNumber();
DeviceManager *const devMgr = DeviceManager::instance();
const Utils::Id id = dev->id();
@@ -457,15 +449,7 @@ void AndroidDeviceManager::updateDeviceState(const ProjectExplorer::IDevice::Ptr
return;
}
- const QStringList args = AndroidDeviceInfo::adbSelector(serial) << "shell" << "echo" << "1";
- const SdkToolResult result = AndroidManager::runAdbCommand(args);
- const int success = result.success();
- if (success)
- devMgr->setDeviceState(id, IDevice::DeviceReadyToUse);
- else if (dev->machineType() == IDevice::Emulator || result.stdErr().contains("unauthorized"))
- devMgr->setDeviceState(id, IDevice::DeviceConnected);
- else
- devMgr->setDeviceState(id, IDevice::DeviceDisconnected);
+ devMgr->setDeviceState(id, getDeviceState(serial, dev->machineType()));
}
void AndroidDeviceManager::startAvd(const ProjectExplorer::IDevice::Ptr &device, QWidget *parent)
@@ -523,6 +507,13 @@ void AndroidDeviceManager::handleAvdRemoved()
}
}
+QString AndroidDeviceManager::emulatorName(const QString &serialNumber) const
+{
+ QStringList args = AndroidDeviceInfo::adbSelector(serialNumber);
+ args.append({"emu", "avd", "name"});
+ return AndroidManager::runAdbCommand(args).stdOut();
+}
+
void AndroidDeviceManager::setEmulatorArguments(QWidget *parent)
{
const QString helpUrl =
@@ -546,73 +537,121 @@ void AndroidDeviceManager::setEmulatorArguments(QWidget *parent)
m_androidConfig.setEmulatorArgs(Utils::ProcessArgs::splitArgs(dialog.textValue()));
}
-void AndroidDeviceManager::setupDevicesWatcher()
+QString AndroidDeviceManager::getRunningAvdsSerialNumber(const QString &name) const
{
- if (!m_devicesUpdaterTimer.isActive()) {
- // The call to avdmanager is always slower than the call to adb devices,
- // so connecting the slot to the slower call should be enough.
- connect(&m_avdsFutureWatcher, &QFutureWatcherBase::finished,
- this, &AndroidDeviceManager::devicesListUpdated);
- connect(&m_devicesUpdaterTimer, &QTimer::timeout, this, [this]() {
- updateDevicesList();
- });
- m_devicesUpdaterTimer.start(deviceUpdaterMsInterval);
+ for (const AndroidDeviceInfo &dev : m_androidConfig.connectedDevices()) {
+ if (!dev.serialNumber.startsWith("emulator"))
+ continue;
+ const QString stdOut = emulatorName(dev.serialNumber);
+ if (stdOut.isEmpty())
+ continue; // Not an avd
+ const QStringList outputLines = stdOut.split('\n');
+ if (outputLines.size() > 1 && outputLines.first() == name)
+ return dev.serialNumber;
}
- updateDevicesListOnce();
+
+ return {};
}
-void AndroidDeviceManager::devicesListUpdated()
+void AndroidDeviceManager::setupDevicesWatcher()
{
- QVector<AndroidDeviceInfo> connectedDevicesInfos;
- connectedDevicesInfos = m_devicesFutureWatcher.result();
+ if (!m_androidConfig.adbToolPath().exists()) {
+ qCDebug(androidDeviceLog) << "Cannot start ADB device watcher"
+ << "because adb path does not exist.";
+ return;
+ }
- // For checking the state of avds, since running avds are assigned a serial number of
- // the form emulator-xxxx, thus we have to manually check for the names.
- const QStringList runningAvds = m_androidConfig.getRunningAvdsFromDevices(connectedDevicesInfos);
+ if (!m_adbDeviceWatcherProcess)
+ m_adbDeviceWatcherProcess.reset(new Utils::QtcProcess(this));
- AndroidDeviceInfoList devices = m_avdsFutureWatcher.result();
- const QSet<QString> startedAvds = Utils::transform<QSet>(connectedDevicesInfos,
- &AndroidDeviceInfo::avdname);
- for (const AndroidDeviceInfo &dev : devices)
- if (!startedAvds.contains(dev.avdname))
- connectedDevicesInfos << dev;
+ if (m_adbDeviceWatcherProcess->isRunning()) {
+ qCDebug(androidDeviceLog) << "ADB device watcher is already running.";
+ return;
+ }
- DeviceManager *const devMgr = DeviceManager::instance();
+ connect(m_adbDeviceWatcherProcess.get(), &Utils::QtcProcess::finished, this,
+ []() { qCDebug(androidDeviceLog) << "ADB device watcher finished."; });
- QVector<IDevice::ConstPtr> existingDevs;
- QVector<IDevice::ConstPtr> connectedDevs;
+ connect(m_adbDeviceWatcherProcess.get(), &Utils::QtcProcess::errorOccurred, this,
+ [this](QProcess::ProcessError error) {
+ qCDebug(androidDeviceLog) << "ADB device watcher encountered an error:"
+ << m_adbDeviceWatcherProcess->errorString();
+ if (!m_adbDeviceWatcherProcess->isRunning()) {
+ qCDebug(androidDeviceLog) << "Restarting the ADB device watcher now.";
+ QTimer::singleShot(0, m_adbDeviceWatcherProcess.get(), &Utils::QtcProcess::start);
+ }
+ });
+
+ m_adbDeviceWatcherProcess->setStdErrLineCallback([](const QString &error) {
+ qCDebug(androidDeviceLog) << "ADB device watcher error" << error; });
+ m_adbDeviceWatcherProcess->setStdOutLineCallback([this](const QString &output) {
+ HandleDevicesListChange(output);
+ });
+
+ const Utils::CommandLine command = Utils::CommandLine(m_androidConfig.adbToolPath(),
+ {"track-devices"});
+ m_adbDeviceWatcherProcess->setCommand(command);
+ m_adbDeviceWatcherProcess->setEnvironment(AndroidConfigurations::toolsEnvironment(m_androidConfig));
+ m_adbDeviceWatcherProcess->start();
+
+ // Setup AVD filesystem watcher to listen for changes when an avd is created/deleted,
+ // or started/stopped
+ QString avdEnvVar = qEnvironmentVariable("ANDROID_AVD_HOME");
+ if (avdEnvVar.isEmpty()) {
+ avdEnvVar = qEnvironmentVariable("ANDROID_SDK_HOME");
+ if (avdEnvVar.isEmpty())
+ avdEnvVar = qEnvironmentVariable("HOME");
+ avdEnvVar.append("/.android/avd");
+ }
+ const Utils::FilePath avdPath = Utils::FilePath::fromUserInput(avdEnvVar);
+ m_avdFileSystemWatcher.addPath(avdPath.toString());
+ connect(&m_avdsFutureWatcher, &QFutureWatcherBase::finished,
+ this, &AndroidDeviceManager::HandleAvdsListChange);
+ connect(&m_avdFileSystemWatcher, &QFileSystemWatcher::directoryChanged, this, [this]() {
+ // If the avd list upate command is running no need to call it again.
+ if (!m_avdsFutureWatcher.isRunning())
+ updateAvdsList();
+ });
+ // Call initial update
+ updateAvdsList();
+}
+void AndroidDeviceManager::HandleAvdsListChange()
+{
+ DeviceManager *const devMgr = DeviceManager::instance();
+
+ QVector<IDevice::ConstPtr> existingAvds;
for (int i = 0; i < devMgr->deviceCount(); ++i) {
const IDevice::ConstPtr dev = devMgr->deviceAt(i);
- if (dev->id().toString().startsWith(Constants::ANDROID_DEVICE_ID)) {
- existingDevs.append(dev);
- }
+ const bool isEmulator = dev->machineType() == IDevice::Emulator;
+ if (isEmulator && dev->type() == Constants::ANDROID_DEVICE_TYPE)
+ existingAvds.append(dev);
}
- for (auto item : connectedDevicesInfos) {
+ QVector<IDevice::ConstPtr> connectedDevs;
+ for (auto item : m_avdsFutureWatcher.result()) {
const Utils::Id deviceId = AndroidDevice::idFromDeviceInfo(item);
const QString displayName = AndroidDevice::displayNameFromInfo(item);
IDevice::ConstPtr dev = devMgr->find(deviceId);
if (!dev.isNull()) {
- if (dev->displayName() == displayName) {
- IDevice::DeviceState newState;
- // If an AVD is not already running set its state to Connected instead of
- // ReadyToUse.
- if (dev->machineType() == IDevice::Emulator && !runningAvds.contains(displayName))
- newState = IDevice::DeviceConnected;
- else
- newState = item.state;
- if (dev->deviceState() != newState) {
+ const auto androidDev = static_cast<const AndroidDevice *>(dev.data());
+ // DeviceManager doens't seem to hav a way to directly update the name, if the name
+ // of the device has changed, remove it and register it again with the new name.
+ // Also account for the case of an AVD registered through old QC which might have
+ // invalid data by checking the sdcard size value.
+ if (dev->displayName() != displayName || androidDev->sdcardSize() == tr("Unknown")) {
+ devMgr->removeDevice(dev->id());
+ } else {
+ // Find the state of the AVD retrieved from the AVD watcher
+ const QString serial = getRunningAvdsSerialNumber(item.avdname);
+ const IDevice::DeviceState state = getDeviceState(serial, IDevice::Emulator);
+ if (dev->deviceState() != state) {
+ devMgr->setDeviceState(dev->id(), state);
qCDebug(androidDeviceLog, "Device id \"%s\" changed its state.",
dev->id().toString().toUtf8().data());
- devMgr->setDeviceState(dev->id(), newState);
}
connectedDevs.append(dev);
continue;
- } else {
- // DeviceManager doens't seem to hav a way to directly update the name, if the name
- // of the device has changed, remove it and register it again with the new name.
- devMgr->removeDevice(dev->id());
}
}
@@ -625,17 +664,79 @@ void AndroidDeviceManager::devicesListUpdated()
qCDebug(androidDeviceLog, "Registering new Android device id \"%s\".",
newDev->id().toString().toUtf8().data());
const IDevice::ConstPtr constNewDev = IDevice::ConstPtr(newDev);
- devMgr->addDevice(constNewDev);
+ devMgr->addDevice(IDevice::ConstPtr(constNewDev));
connectedDevs.append(constNewDev);
+
+ // Set devices no longer connected to disconnected state.
+ for (const IDevice::ConstPtr &dev : existingAvds) {
+ if (!connectedDevs.contains(dev)) {
+ qCDebug(androidDeviceLog, "Removing AVD id \"%s\" because it no longer exists.",
+ dev->id().toString().toUtf8().data());
+ devMgr->removeDevice(dev->id());
+ }
+ }
}
+}
- // Set devices no longer connected to disconnected state.
- for (const IDevice::ConstPtr &dev : existingDevs) {
- if (dev->id() != Constants::ANDROID_DEVICE_ID && !connectedDevs.contains(dev)
- && dev->deviceState() != IDevice::DeviceDisconnected) {
- qCDebug(androidDeviceLog, "Device id \"%s\" is no longer connected.",
- dev->id().toString().toUtf8().data());
- devMgr->setDeviceState(dev->id(), IDevice::DeviceDisconnected);
+void AndroidDeviceManager::HandleDevicesListChange(const QString &serialNumber)
+{
+ DeviceManager *const devMgr = DeviceManager::instance();
+ const QStringList serialBits = serialNumber.split('\t');
+ if (serialBits.size() < 2)
+ return;
+
+ // Sample output of adb track-devices, the first 4 digits are for state type
+ // and sometimes 4 zeros are reported as part for the serial number.
+ // 00546db0e8d7 authorizing
+ // 00546db0e8d7 device
+ // 0000001711201JEC207789 offline
+ // emulator-5554 device
+ QString dirtySerial = serialBits.first().trimmed();
+ if (dirtySerial.startsWith("0000"))
+ dirtySerial = dirtySerial.mid(4);
+ if (dirtySerial.startsWith("00"))
+ dirtySerial = dirtySerial.mid(4);
+ const bool isEmulator = dirtySerial.startsWith("emulator");
+
+ const QString &serial = dirtySerial;
+ const QString stateStr = serialBits.at(1).trimmed();
+
+ IDevice::DeviceState state;
+ if (stateStr == "device")
+ state = IDevice::DeviceReadyToUse;
+ else if (stateStr == "offline")
+ state = IDevice::DeviceDisconnected;
+ else
+ state = IDevice::DeviceConnected;
+
+ if (isEmulator) {
+ const QString avdName = emulatorName(serial);
+ const Utils::Id avdId = Utils::Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + avdName);
+ devMgr->setDeviceState(avdId, state);
+ } else {
+ const Utils::Id id = Utils::Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + serial);
+ const QString displayName = AndroidConfigurations::currentConfig().getProductModel(serial);
+ if (IDevice::ConstPtr dev = devMgr->find(id)) {
+ // DeviceManager doens't seem to have a way to directly update the name, if the name
+ // of the device has changed, remove it and register it again with the new name.
+ if (dev->displayName() == displayName)
+ devMgr->setDeviceState(id, state);
+ else
+ devMgr->removeDevice(id);
+ } else {
+ AndroidDevice *newDev = new AndroidDevice();
+ newDev->setupId(IDevice::AutoDetected, id);
+ newDev->setDisplayName(displayName);
+ newDev->setMachineType(IDevice::Hardware);
+ newDev->setDeviceState(state);
+
+ newDev->setExtraData(Constants::AndroidSerialNumber, serial);
+ newDev->setExtraData(Constants::AndroidCpuAbi, m_androidConfig.getAbis(serial));
+ newDev->setExtraData(Constants::AndroidSdk, m_androidConfig.getSDKVersion(serial));
+
+ qCDebug(androidDeviceLog, "Registering new Android device id \"%s\".",
+ newDev->id().toString().toUtf8().data());
+ devMgr->addDevice(IDevice::ConstPtr(newDev));
}
}
}
@@ -652,9 +753,10 @@ AndroidDeviceManager::AndroidDeviceManager(QObject *parent)
m_avdManager(m_androidConfig)
{
connect(qApp, &QCoreApplication::aboutToQuit, this, [this]() {
- m_devicesUpdaterTimer.stop();
+ m_adbDeviceWatcherProcess->terminate();
+ m_adbDeviceWatcherProcess->waitForFinished();
+ m_adbDeviceWatcherProcess.reset();
m_avdsFutureWatcher.waitForFinished();
- m_devicesFutureWatcher.waitForFinished();
m_removeAvdFutureWatcher.waitForFinished();
});
diff --git a/src/plugins/android/androiddevice.h b/src/plugins/android/androiddevice.h
index 3d08f09315..8a8abe70ad 100644
--- a/src/plugins/android/androiddevice.h
+++ b/src/plugins/android/androiddevice.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
** Contact: https://www.qt.io/licensing/
**
@@ -33,8 +33,10 @@
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/devicesupport/idevicefactory.h>
+#include <utils/qtcprocess.h>
+
#include <QFutureWatcher>
-#include <QTimer>
+#include <QFileSystemWatcher>
namespace Android {
namespace Internal {
@@ -70,6 +72,7 @@ public:
QString androidTargetName() const;
QString sdcardSize() const;
QString openGlStatusString() const;
+ // TODO: remove not used
AndroidConfig::OpenGl openGlStatus() const;
protected:
@@ -98,24 +101,29 @@ class AndroidDeviceManager : public QObject
public:
static AndroidDeviceManager *instance();
void setupDevicesWatcher();
- void updateDevicesList();
- void updateDevicesListOnce();
- void updateDeviceState(const ProjectExplorer::IDevice::Ptr &device);
+ void updateAvdsList();
+ IDevice::DeviceState getDeviceState(const QString &serial, IDevice::MachineType type) const;
+ void updateDeviceState(const ProjectExplorer::IDevice::ConstPtr &device);
void startAvd(const ProjectExplorer::IDevice::Ptr &device, QWidget *parent = nullptr);
void eraseAvd(const ProjectExplorer::IDevice::Ptr &device, QWidget *parent = nullptr);
void setEmulatorArguments(QWidget *parent = nullptr);
+ QString getRunningAvdsSerialNumber(const QString &name) const;
+
private:
AndroidDeviceManager(QObject *parent = nullptr);
- void devicesListUpdated();
+ void HandleDevicesListChange(const QString &serialNumber);
+ void HandleAvdsListChange();
void handleAvdRemoved();
+ QString emulatorName(const QString &serialNumber) const;
+
QFutureWatcher<AndroidDeviceInfoList> m_avdsFutureWatcher;
- QFutureWatcher<QVector<AndroidDeviceInfo>> m_devicesFutureWatcher;
QFutureWatcher<QPair<ProjectExplorer::IDevice::ConstPtr, bool>> m_removeAvdFutureWatcher;
- QTimer m_devicesUpdaterTimer;
+ QFileSystemWatcher m_avdFileSystemWatcher;
+ std::unique_ptr<Utils::QtcProcess> m_adbDeviceWatcherProcess;
AndroidConfig &m_androidConfig;
AndroidAvdManager m_avdManager;
};