diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index dcbc8f401a4..8e196299275 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -521,16 +521,21 @@ FileName AndroidConfig::keytoolPath() const } QVector AndroidConfig::connectedDevices(QString *error) const +{ + return connectedDevices(adbToolPath().toString(), error); +} + +QVector AndroidConfig::connectedDevices(const QString &adbToolPath, QString *error) { QVector 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 adbDevs = adbProc.readAll().trimmed().split('\n'); @@ -546,13 +551,13 @@ QVector 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 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> AndroidConfig::androidVirtualDevicesFuture() { - return QtConcurrent::run(&AndroidConfig::androidVirtualDevicesImpl, androidToolPath(), androidToolEnvironment()); + return QtConcurrent::run(&AndroidConfig::androidVirtualDevices, androidToolPath().toString(), androidToolEnvironment()); } QVector AndroidConfig::androidVirtualDevices() const { - return androidVirtualDevicesImpl(androidToolPath(), androidToolEnvironment()); + return androidVirtualDevices(androidToolPath().toString(), androidToolEnvironment()); } -QVector AndroidConfig::androidVirtualDevicesImpl(const FileName &androidTool, const Environment &environment) +QVector AndroidConfig::androidVirtualDevices(const QString &androidTool, const Environment &environment) { QVector 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; diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h index 7ac2f929e55..687ec1cfce0 100644 --- a/src/plugins/android/androidconfigurations.h +++ b/src/plugins/android/androidconfigurations.h @@ -148,9 +148,11 @@ public: bool removeAVD(const QString &name) const; QVector connectedDevices(QString *error = 0) const; + static QVector connectedDevices(const QString &adbToolPath, QString *error = 0); QFuture > androidVirtualDevicesFuture(); QVector androidVirtualDevices() const; + static QVector 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 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; diff --git a/src/plugins/android/androiddevicedialog.cpp b/src/plugins/android/androiddevicedialog.cpp index b0e531cf4c9..f4916d5219e 100644 --- a/src/plugins/android/androiddevicedialog.cpp +++ b/src/plugins/android/androiddevicedialog.cpp @@ -32,6 +32,9 @@ #include "androidmanager.h" #include "ui_androiddevicedialog.h" +#include +#include + #include #include #include @@ -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 AndroidDeviceDialog::refreshDevices(const QString &adbToolPath, + const QString &androidToolPath, + const Utils::Environment &environment) +{ QVector 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 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(m_ui->deviceView->currentIndex().internalPointer()); + bool enable = node && !node->deviceInfo().serialNumber.isEmpty(); + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enable); } // Does not work. diff --git a/src/plugins/android/androiddevicedialog.h b/src/plugins/android/androiddevicedialog.h index cae5d9c6b30..127295d5d4d 100644 --- a/src/plugins/android/androiddevicedialog.h +++ b/src/plugins/android/androiddevicedialog.h @@ -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 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 m_futureWatcher; + QString m_serialNumberFromAdd; + QFutureWatcher m_futureWatcherAddDevice; + QFutureWatcher> m_futureWatcherRefreshDevices; }; }