forked from qt-creator/qt-creator
AndroidDeviceDialog: Move refreshing devices to a diffrent thread
Easy to do and makes the dialog feel marginally nicer. Task-number: QTCREATORBUG-13123 Change-Id: I64098f1fd751100d40227c298a9e7eb358552bfb Reviewed-by: BogDan Vatra <bogdan@kde.org>
This commit is contained in:
@@ -521,16 +521,21 @@ FileName AndroidConfig::keytoolPath() const
|
||||
}
|
||||
|
||||
QVector<AndroidDeviceInfo> AndroidConfig::connectedDevices(QString *error) const
|
||||
{
|
||||
return connectedDevices(adbToolPath().toString(), error);
|
||||
}
|
||||
|
||||
QVector<AndroidDeviceInfo> AndroidConfig::connectedDevices(const QString &adbToolPath, QString *error)
|
||||
{
|
||||
QVector<AndroidDeviceInfo> devices;
|
||||
QProcess adbProc;
|
||||
adbProc.start(adbToolPath().toString(), QStringList() << QLatin1String("devices"));
|
||||
adbProc.start(adbToolPath, QStringList() << QLatin1String("devices"));
|
||||
if (!adbProc.waitForFinished(10000)) {
|
||||
adbProc.kill();
|
||||
if (error)
|
||||
*error = QApplication::translate("AndroidConfiguration",
|
||||
"Could not run: %1")
|
||||
.arg(adbToolPath().toString() + QLatin1String(" devices"));
|
||||
.arg(adbToolPath + QLatin1String(" devices"));
|
||||
return devices;
|
||||
}
|
||||
QList<QByteArray> adbDevs = adbProc.readAll().trimmed().split('\n');
|
||||
@@ -546,13 +551,13 @@ QVector<AndroidDeviceInfo> AndroidConfig::connectedDevices(QString *error) const
|
||||
foreach (const QByteArray &device, adbDevs) {
|
||||
const QString serialNo = QString::fromLatin1(device.left(device.indexOf('\t')).trimmed());
|
||||
const QString deviceType = QString::fromLatin1(device.mid(device.indexOf('\t'))).trimmed();
|
||||
if (isBootToQt(serialNo))
|
||||
if (isBootToQt(adbToolPath, serialNo))
|
||||
continue;
|
||||
AndroidDeviceInfo dev;
|
||||
dev.serialNumber = serialNo;
|
||||
dev.type = serialNo.startsWith(QLatin1String("emulator")) ? AndroidDeviceInfo::Emulator : AndroidDeviceInfo::Hardware;
|
||||
dev.sdk = getSDKVersion(dev.serialNumber);
|
||||
dev.cpuAbi = getAbis(dev.serialNumber);
|
||||
dev.sdk = getSDKVersion(adbToolPath, dev.serialNumber);
|
||||
dev.cpuAbi = getAbis(adbToolPath, dev.serialNumber);
|
||||
if (deviceType == QLatin1String("unauthorized"))
|
||||
dev.state = AndroidDeviceInfo::UnAuthorizedState;
|
||||
else if (deviceType == QLatin1String("offline"))
|
||||
@@ -566,7 +571,7 @@ QVector<AndroidDeviceInfo> AndroidConfig::connectedDevices(QString *error) const
|
||||
if (devices.isEmpty() && error)
|
||||
*error = QApplication::translate("AndroidConfiguration",
|
||||
"No devices found in output of: %1")
|
||||
.arg(adbToolPath().toString() + QLatin1String(" devices"));
|
||||
.arg(adbToolPath + QLatin1String(" devices"));
|
||||
return devices;
|
||||
}
|
||||
|
||||
@@ -657,20 +662,20 @@ bool AndroidConfig::removeAVD(const QString &name) const
|
||||
|
||||
QFuture<QVector<AndroidDeviceInfo>> AndroidConfig::androidVirtualDevicesFuture()
|
||||
{
|
||||
return QtConcurrent::run(&AndroidConfig::androidVirtualDevicesImpl, androidToolPath(), androidToolEnvironment());
|
||||
return QtConcurrent::run(&AndroidConfig::androidVirtualDevices, androidToolPath().toString(), androidToolEnvironment());
|
||||
}
|
||||
|
||||
QVector<AndroidDeviceInfo> AndroidConfig::androidVirtualDevices() const
|
||||
{
|
||||
return androidVirtualDevicesImpl(androidToolPath(), androidToolEnvironment());
|
||||
return androidVirtualDevices(androidToolPath().toString(), androidToolEnvironment());
|
||||
}
|
||||
|
||||
QVector<AndroidDeviceInfo> AndroidConfig::androidVirtualDevicesImpl(const FileName &androidTool, const Environment &environment)
|
||||
QVector<AndroidDeviceInfo> AndroidConfig::androidVirtualDevices(const QString &androidTool, const Environment &environment)
|
||||
{
|
||||
QVector<AndroidDeviceInfo> devices;
|
||||
QProcess proc;
|
||||
proc.setProcessEnvironment(environment.toProcessEnvironment());
|
||||
proc.start(androidTool.toString(),
|
||||
proc.start(androidTool,
|
||||
QStringList() << QLatin1String("list") << QLatin1String("avd")); // list available AVDs
|
||||
if (!proc.waitForFinished(10000)) {
|
||||
proc.terminate();
|
||||
@@ -833,6 +838,11 @@ QString AndroidConfig::waitForAvd(int apiLevel, const QString &cpuAbi, const QFu
|
||||
}
|
||||
|
||||
bool AndroidConfig::isBootToQt(const QString &device) const
|
||||
{
|
||||
return isBootToQt(adbToolPath().toString(), device);
|
||||
}
|
||||
|
||||
bool AndroidConfig::isBootToQt(const QString &adbToolPath, const QString &device)
|
||||
{
|
||||
// workaround for '????????????' serial numbers
|
||||
QStringList arguments = AndroidDeviceInfo::adbSelector(device);
|
||||
@@ -840,7 +850,7 @@ bool AndroidConfig::isBootToQt(const QString &device) const
|
||||
<< QLatin1String("ls -l /system/bin/appcontroller || ls -l /usr/bin/appcontroller && echo Boot2Qt");
|
||||
|
||||
QProcess adbProc;
|
||||
adbProc.start(adbToolPath().toString(), arguments);
|
||||
adbProc.start(adbToolPath, arguments);
|
||||
if (!adbProc.waitForFinished(10000)) {
|
||||
adbProc.kill();
|
||||
return false;
|
||||
@@ -848,7 +858,8 @@ bool AndroidConfig::isBootToQt(const QString &device) const
|
||||
return adbProc.readAll().contains("Boot2Qt");
|
||||
}
|
||||
|
||||
QString AndroidConfig::getDeviceProperty(const QString &device, const QString &property) const
|
||||
|
||||
QString AndroidConfig::getDeviceProperty(const QString &adbToolPath, const QString &device, const QString &property)
|
||||
{
|
||||
// workaround for '????????????' serial numbers
|
||||
QStringList arguments = AndroidDeviceInfo::adbSelector(device);
|
||||
@@ -856,7 +867,7 @@ QString AndroidConfig::getDeviceProperty(const QString &device, const QString &p
|
||||
<< property;
|
||||
|
||||
QProcess adbProc;
|
||||
adbProc.start(adbToolPath().toString(), arguments);
|
||||
adbProc.start(adbToolPath, arguments);
|
||||
if (!adbProc.waitForFinished(10000)) {
|
||||
adbProc.kill();
|
||||
return QString();
|
||||
@@ -867,7 +878,12 @@ QString AndroidConfig::getDeviceProperty(const QString &device, const QString &p
|
||||
|
||||
int AndroidConfig::getSDKVersion(const QString &device) const
|
||||
{
|
||||
QString tmp = getDeviceProperty(device, QLatin1String("ro.build.version.sdk"));
|
||||
return getSDKVersion(adbToolPath().toString(), device);
|
||||
}
|
||||
|
||||
int AndroidConfig::getSDKVersion(const QString &adbToolPath, const QString &device)
|
||||
{
|
||||
QString tmp = getDeviceProperty(adbToolPath, device, QLatin1String("ro.build.version.sdk"));
|
||||
if (tmp.isEmpty())
|
||||
return -1;
|
||||
return tmp.trimmed().toInt();
|
||||
@@ -905,7 +921,7 @@ QString AndroidConfig::getProductModel(const QString &device) const
|
||||
if (m_serialNumberToDeviceName.contains(device))
|
||||
return m_serialNumberToDeviceName.value(device);
|
||||
|
||||
QString model = getDeviceProperty(device, QLatin1String("ro.product.model")).trimmed();
|
||||
QString model = getDeviceProperty(adbToolPath().toString(), device, QLatin1String("ro.product.model")).trimmed();
|
||||
if (model.isEmpty())
|
||||
return device;
|
||||
|
||||
@@ -933,6 +949,11 @@ bool AndroidConfig::hasFinishedBooting(const QString &device) const
|
||||
}
|
||||
|
||||
QStringList AndroidConfig::getAbis(const QString &device) const
|
||||
{
|
||||
return getAbis(adbToolPath().toString(), device);
|
||||
}
|
||||
|
||||
QStringList AndroidConfig::getAbis(const QString &adbToolPath, const QString &device)
|
||||
{
|
||||
QStringList result;
|
||||
// First try via ro.product.cpu.abilist
|
||||
@@ -940,7 +961,7 @@ QStringList AndroidConfig::getAbis(const QString &device) const
|
||||
arguments << QLatin1String("shell") << QLatin1String("getprop");
|
||||
arguments << QLatin1String("ro.product.cpu.abilist");
|
||||
QProcess adbProc;
|
||||
adbProc.start(adbToolPath().toString(), arguments);
|
||||
adbProc.start(adbToolPath, arguments);
|
||||
if (!adbProc.waitForFinished(10000)) {
|
||||
adbProc.kill();
|
||||
return result;
|
||||
@@ -962,7 +983,7 @@ QStringList AndroidConfig::getAbis(const QString &device) const
|
||||
arguments << QString::fromLatin1("ro.product.cpu.abi%1").arg(i);
|
||||
|
||||
QProcess adbProc;
|
||||
adbProc.start(adbToolPath().toString(), arguments);
|
||||
adbProc.start(adbToolPath, arguments);
|
||||
if (!adbProc.waitForFinished(10000)) {
|
||||
adbProc.kill();
|
||||
return result;
|
||||
|
||||
@@ -148,9 +148,11 @@ public:
|
||||
bool removeAVD(const QString &name) const;
|
||||
|
||||
QVector<AndroidDeviceInfo> connectedDevices(QString *error = 0) const;
|
||||
static QVector<AndroidDeviceInfo> connectedDevices(const QString &adbToolPath, QString *error = 0);
|
||||
|
||||
QFuture<QVector<AndroidDeviceInfo> > androidVirtualDevicesFuture();
|
||||
QVector<AndroidDeviceInfo> androidVirtualDevices() const;
|
||||
static QVector<AndroidDeviceInfo> androidVirtualDevices(const QString &androidTool, const Utils::Environment &environment);
|
||||
|
||||
QString startAVD(const QString &name, int apiLevel, QString cpuAbi) const;
|
||||
bool startAVDAsync(const QString &avdName) const;
|
||||
@@ -173,13 +175,15 @@ public:
|
||||
SdkPlatform highestAndroidSdk() const;
|
||||
private:
|
||||
static CreateAvdInfo createAVDImpl(CreateAvdInfo info, Utils::FileName androidToolPath, Utils::Environment env);
|
||||
static QVector<AndroidDeviceInfo> androidVirtualDevicesImpl(const Utils::FileName &androidTool, const Utils::Environment &environment);
|
||||
QString getDeviceProperty(const QString &device, const QString &property) const;
|
||||
static QString getDeviceProperty(const QString &adbToolPath, const QString &device, const QString &property);
|
||||
|
||||
Utils::FileName toolPath(const ProjectExplorer::Abi &abi, const QString &ndkToolChainVersion) const;
|
||||
Utils::FileName openJDKBinPath() const;
|
||||
int getSDKVersion(const QString &device) const;
|
||||
static int getSDKVersion(const QString &adbToolPath, const QString &device);
|
||||
QStringList getAbis(const QString &device) const;
|
||||
static QStringList getAbis(const QString &adbToolPath, const QString &device);
|
||||
static bool isBootToQt(const QString &adbToolPath, const QString &device);
|
||||
bool isBootToQt(const QString &device) const;
|
||||
|
||||
void updateAvailableSdkPlatforms() const;
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
#include "androidmanager.h"
|
||||
#include "ui_androiddevicedialog.h"
|
||||
|
||||
#include <utils/environment.h>
|
||||
#include <utils/progressindicator.h>
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QPainter>
|
||||
#include <QStyledItemDelegate>
|
||||
@@ -442,16 +445,27 @@ AndroidDeviceDialog::AndroidDeviceDialog(int apiLevel, const QString &abi, Andro
|
||||
connect(m_ui->deviceView, SIGNAL(doubleClicked(QModelIndex)),
|
||||
this, SLOT(accept()));
|
||||
|
||||
connect(&m_futureWatcher, SIGNAL(finished()),
|
||||
connect(&m_futureWatcherAddDevice, SIGNAL(finished()),
|
||||
this, SLOT(avdAdded()));
|
||||
connect(&m_futureWatcherRefreshDevices, &QFutureWatcherBase::finished,
|
||||
this, &AndroidDeviceDialog::devicesRefreshed);
|
||||
|
||||
refreshDeviceList();
|
||||
|
||||
connect(m_ui->deviceView->selectionModel(), &QItemSelectionModel::currentChanged,
|
||||
this, &AndroidDeviceDialog::enableOkayButton);
|
||||
|
||||
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
|
||||
m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicator::Large, this);
|
||||
m_progressIndicator->attachToWidget(m_ui->deviceView);
|
||||
}
|
||||
|
||||
AndroidDeviceDialog::~AndroidDeviceDialog()
|
||||
{
|
||||
m_futureWatcherAddDevice.waitForFinished();
|
||||
m_futureWatcherRefreshDevices.waitForFinished();
|
||||
delete m_ui;
|
||||
m_futureWatcher.waitForFinished();
|
||||
}
|
||||
|
||||
AndroidDeviceInfo AndroidDeviceDialog::device()
|
||||
@@ -473,17 +487,40 @@ bool AndroidDeviceDialog::saveDeviceSelection()
|
||||
|
||||
void AndroidDeviceDialog::refreshDeviceList()
|
||||
{
|
||||
QString serialNumber;
|
||||
QModelIndex currentIndex = m_ui->deviceView->currentIndex();
|
||||
if (currentIndex.isValid())
|
||||
serialNumber = m_model->device(currentIndex).serialNumber;
|
||||
m_ui->refreshDevicesButton->setEnabled(false);
|
||||
m_futureWatcherRefreshDevices.setFuture(QtConcurrent::run(&AndroidDeviceDialog::refreshDevices,
|
||||
AndroidConfigurations::currentConfig().adbToolPath().toString(),
|
||||
AndroidConfigurations::currentConfig().androidToolPath().toString(),
|
||||
AndroidConfigurations::currentConfig().androidToolEnvironment()));
|
||||
}
|
||||
|
||||
QVector<AndroidDeviceInfo> AndroidDeviceDialog::refreshDevices(const QString &adbToolPath,
|
||||
const QString &androidToolPath,
|
||||
const Utils::Environment &environment)
|
||||
{
|
||||
QVector<AndroidDeviceInfo> devices;
|
||||
foreach (const AndroidDeviceInfo &info, AndroidConfigurations::currentConfig().connectedDevices())
|
||||
foreach (const AndroidDeviceInfo &info, AndroidConfig::connectedDevices(adbToolPath))
|
||||
if (info.type == AndroidDeviceInfo::Hardware)
|
||||
devices << info;
|
||||
|
||||
devices += AndroidConfigurations::currentConfig().androidVirtualDevices();
|
||||
devices += AndroidConfig::androidVirtualDevices(androidToolPath, environment);
|
||||
return devices;
|
||||
}
|
||||
|
||||
void AndroidDeviceDialog::devicesRefreshed()
|
||||
{
|
||||
m_progressIndicator->hide();
|
||||
QString serialNumber;
|
||||
if (!m_serialNumberFromAdd.isEmpty()) {
|
||||
serialNumber = m_serialNumberFromAdd;
|
||||
m_serialNumberFromAdd.clear();
|
||||
} else {
|
||||
QModelIndex currentIndex = m_ui->deviceView->currentIndex();
|
||||
if (currentIndex.isValid())
|
||||
serialNumber = m_model->device(currentIndex).serialNumber;
|
||||
}
|
||||
|
||||
QVector<AndroidDeviceInfo> devices = m_futureWatcherRefreshDevices.result();
|
||||
m_model->setDevices(devices);
|
||||
|
||||
m_ui->deviceView->expand(m_model->index(0, 0));
|
||||
@@ -501,6 +538,8 @@ void AndroidDeviceDialog::refreshDeviceList()
|
||||
m_ui->deviceView->setCurrentIndex(newIndex);
|
||||
|
||||
m_ui->stackedWidget->setCurrentIndex(devices.isEmpty() ? 1 : 0);
|
||||
|
||||
m_ui->refreshDevicesButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void AndroidDeviceDialog::createAvd()
|
||||
@@ -513,21 +552,27 @@ void AndroidDeviceDialog::createAvd()
|
||||
return;
|
||||
}
|
||||
|
||||
m_futureWatcher.setFuture(AndroidConfigurations::currentConfig().createAVD(info));
|
||||
m_futureWatcherAddDevice.setFuture(AndroidConfigurations::currentConfig().createAVD(info));
|
||||
}
|
||||
|
||||
void AndroidDeviceDialog::avdAdded()
|
||||
{
|
||||
m_ui->createAVDButton->setEnabled(true);
|
||||
AndroidConfig::CreateAvdInfo info = m_futureWatcher.result();
|
||||
AndroidConfig::CreateAvdInfo info = m_futureWatcherAddDevice.result();
|
||||
if (!info.error.isEmpty()) {
|
||||
QMessageBox::critical(this, QApplication::translate("AndroidConfig", "Error Creating AVD"), info.error);
|
||||
return;
|
||||
}
|
||||
|
||||
m_serialNumberFromAdd = info.name;
|
||||
refreshDeviceList();
|
||||
QModelIndex index = m_model->indexFor(info.name);
|
||||
m_ui->deviceView->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void AndroidDeviceDialog::enableOkayButton()
|
||||
{
|
||||
AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(m_ui->deviceView->currentIndex().internalPointer());
|
||||
bool enable = node && !node->deviceInfo().serialNumber.isEmpty();
|
||||
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enable);
|
||||
}
|
||||
|
||||
// Does not work.
|
||||
|
||||
@@ -41,6 +41,8 @@ QT_BEGIN_NAMESPACE
|
||||
class QModelIndex;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Utils { class ProgressIndicator; }
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
@@ -67,11 +69,20 @@ private slots:
|
||||
void showHelp();
|
||||
void avdAdded();
|
||||
private:
|
||||
static QVector<AndroidDeviceInfo> refreshDevices(const QString &adbToolPath,
|
||||
const QString &androidToolPath,
|
||||
const Utils::Environment &environment);
|
||||
void devicesRefreshed();
|
||||
void enableOkayButton();
|
||||
|
||||
AndroidDeviceModel *m_model;
|
||||
Ui::AndroidDeviceDialog *m_ui;
|
||||
Utils::ProgressIndicator *m_progressIndicator;
|
||||
int m_apiLevel;
|
||||
QString m_abi;
|
||||
QFutureWatcher<AndroidConfig::CreateAvdInfo> m_futureWatcher;
|
||||
QString m_serialNumberFromAdd;
|
||||
QFutureWatcher<AndroidConfig::CreateAvdInfo> m_futureWatcherAddDevice;
|
||||
QFutureWatcher<QVector<AndroidDeviceInfo>> m_futureWatcherRefreshDevices;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user