| 
									
										
										
										
											2016-01-15 14:57:40 +01:00
										 |  |  | /****************************************************************************
 | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  | ** Copyright (C) 2022 The Qt Company Ltd. | 
					
						
							| 
									
										
										
										
											2016-01-15 14:57:40 +01:00
										 |  |  | ** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com> | 
					
						
							|  |  |  | ** Contact: https://www.qt.io/licensing/
 | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ** This file is part of Qt Creator. | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ** Commercial License Usage | 
					
						
							|  |  |  | ** Licensees holding valid commercial Qt licenses may use this file in | 
					
						
							|  |  |  | ** accordance with the commercial license agreement provided with the | 
					
						
							|  |  |  | ** Software or, alternatively, in accordance with the terms contained in | 
					
						
							| 
									
										
										
										
											2016-01-15 14:57:40 +01:00
										 |  |  | ** a written agreement between you and The Qt Company. For licensing terms | 
					
						
							|  |  |  | ** and conditions see https://www.qt.io/terms-conditions. For further
 | 
					
						
							|  |  |  | ** information use the contact form at https://www.qt.io/contact-us.
 | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2016-01-15 14:57:40 +01:00
										 |  |  | ** GNU General Public License Usage | 
					
						
							|  |  |  | ** Alternatively, this file may be used under the terms of the GNU | 
					
						
							|  |  |  | ** General Public License version 3 as published by the Free Software | 
					
						
							|  |  |  | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | 
					
						
							|  |  |  | ** included in the packaging of this file. Please review the following | 
					
						
							|  |  |  | ** information to ensure the GNU General Public License requirements will | 
					
						
							|  |  |  | ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
 | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ****************************************************************************/ | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "androiddevice.h"
 | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "androidavdmanager.h"
 | 
					
						
							|  |  |  | #include "androidconfigurations.h"
 | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | #include "androidconstants.h"
 | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  | #include "androidmanager.h"
 | 
					
						
							| 
									
										
										
										
											2013-09-30 13:20:02 +02:00
										 |  |  | #include "androidsignaloperation.h"
 | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | #include "avddialog.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <coreplugin/icore.h>
 | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | #include <projectexplorer/devicesupport/devicemanager.h>
 | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  | #include <projectexplorer/devicesupport/idevicewidget.h>
 | 
					
						
							| 
									
										
										
										
											2021-11-10 22:38:59 +01:00
										 |  |  | #include <projectexplorer/kitinformation.h>
 | 
					
						
							| 
									
										
										
										
											2022-06-22 15:43:33 +02:00
										 |  |  | #include <projectexplorer/projectexplorerconstants.h>
 | 
					
						
							| 
									
										
										
										
											2016-06-03 19:11:29 +02:00
										 |  |  | #include <projectexplorer/runconfiguration.h>
 | 
					
						
							| 
									
										
										
										
											2021-11-10 22:38:59 +01:00
										 |  |  | #include <projectexplorer/session.h>
 | 
					
						
							|  |  |  | #include <projectexplorer/target.h>
 | 
					
						
							| 
									
										
										
										
											2016-06-03 19:11:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | #include <utils/qtcprocess.h>
 | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | #include <utils/runextensions.h>
 | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  | #include <utils/url.h>
 | 
					
						
							| 
									
										
										
										
											2017-10-25 16:18:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | #include <QEventLoop>
 | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  | #include <QFormLayout>
 | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | #include <QInputDialog>
 | 
					
						
							| 
									
										
										
										
											2018-07-17 13:58:50 +02:00
										 |  |  | #include <QLoggingCategory>
 | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | #include <QMessageBox>
 | 
					
						
							|  |  |  | #include <QPushButton>
 | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  | #include <QTimer>
 | 
					
						
							| 
									
										
										
										
											2022-02-22 21:31:12 +02:00
										 |  |  | #include <QRegularExpression>
 | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <utils/qtcprocess.h>
 | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-26 17:41:52 +02:00
										 |  |  | using namespace ProjectExplorer; | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  | using namespace Utils; | 
					
						
							| 
									
										
										
										
											2012-07-26 17:41:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | namespace { | 
					
						
							|  |  |  | static Q_LOGGING_CATEGORY(androidDeviceLog, "qtc.android.androiddevice", QtWarningMsg) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | namespace Android { | 
					
						
							|  |  |  | namespace Internal { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  | static constexpr char ipRegexStr[] = "(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})"; | 
					
						
							|  |  |  | static const QRegularExpression ipRegex = QRegularExpression(ipRegexStr); | 
					
						
							|  |  |  | static constexpr char wifiDevicePort[] = "5555"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  | class AndroidDeviceWidget : public IDeviceWidget | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     AndroidDeviceWidget(const ProjectExplorer::IDevice::Ptr &device); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void updateDeviceFromUi() final {} | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  |     static QString dialogTitle(); | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  |     static bool messageDialog(const QString &msg, QMessageBox::Icon icon, QWidget *parent = nullptr); | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  |     static bool criticalDialog(const QString &error, QWidget *parent = nullptr); | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  |     static bool infoDialog(const QString &msg, QWidget *parent = nullptr); | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  |     static bool questionDialog(const QString &question, QWidget *parent = nullptr); | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AndroidDeviceWidget::AndroidDeviceWidget(const IDevice::Ptr &device) | 
					
						
							|  |  |  |     : IDeviceWidget(device) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const auto dev = qSharedPointerCast<AndroidDevice>(device); | 
					
						
							|  |  |  |     const auto formLayout = new QFormLayout(this); | 
					
						
							|  |  |  |     formLayout->setFormAlignment(Qt::AlignLeft); | 
					
						
							|  |  |  |     formLayout->setContentsMargins(0, 0, 0, 0); | 
					
						
							|  |  |  |     setLayout(formLayout); | 
					
						
							|  |  |  |     formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!dev->isValid()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     formLayout->addRow(AndroidDevice::tr("Device name:"), new QLabel(dev->displayName())); | 
					
						
							|  |  |  |     formLayout->addRow(AndroidDevice::tr("Device type:"), new QLabel(dev->deviceTypeName())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QString serialNumber = dev->serialNumber(); | 
					
						
							| 
									
										
										
										
											2021-10-28 10:03:28 +02:00
										 |  |  |     const QString printableSerialNumber = serialNumber.isEmpty() ? AndroidDevice::tr("Unknown") | 
					
						
							|  |  |  |                                                                  : serialNumber; | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  |     formLayout->addRow(AndroidDevice::tr("Serial number:"), new QLabel(printableSerialNumber)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QString abis = dev->supportedAbis().join(", "); | 
					
						
							|  |  |  |     formLayout->addRow(AndroidDevice::tr("CPU architecture:"), new QLabel(abis)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const auto osString = QString("%1 (SDK %2)").arg(dev->androidVersion()).arg(dev->sdkLevel()); | 
					
						
							|  |  |  |     formLayout->addRow(AndroidDevice::tr("OS version:"), new QLabel(osString)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-07 11:10:47 +03:00
										 |  |  |     if (dev->machineType() == IDevice::Hardware) { | 
					
						
							| 
									
										
										
										
											2021-10-28 10:03:28 +02:00
										 |  |  |         const QString authorizedStr = dev->deviceState() == IDevice::DeviceReadyToUse | 
					
						
							|  |  |  |                                           ? AndroidDevice::tr("Yes") | 
					
						
							|  |  |  |                                           : AndroidDevice::tr("No"); | 
					
						
							| 
									
										
										
										
											2021-10-07 11:10:47 +03:00
										 |  |  |         formLayout->addRow(AndroidDevice::tr("Authorized:"), new QLabel(authorizedStr)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  |     if (dev->machineType() == IDevice::Emulator) { | 
					
						
							|  |  |  |         const QString targetName = dev->androidTargetName(); | 
					
						
							|  |  |  |         formLayout->addRow(AndroidDevice::tr("Android target flavor:"), new QLabel(targetName)); | 
					
						
							|  |  |  |         formLayout->addRow(AndroidDevice::tr("SD card size:"), new QLabel(dev->sdcardSize())); | 
					
						
							|  |  |  |         formLayout->addRow(AndroidDevice::tr("Skin type:"), new QLabel(dev->skinName())); | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |         const QString openGlStatus = dev->openGLStatus(); | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  |         formLayout->addRow(AndroidDevice::tr("OpenGL status:"), new QLabel(openGlStatus)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | QString AndroidDeviceWidget::dialogTitle() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-10-28 10:03:28 +02:00
										 |  |  |     return AndroidDevice::tr("Android Device Manager"); | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  | bool AndroidDeviceWidget::messageDialog(const QString &msg, QMessageBox::Icon icon, QWidget *parent) | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  |     qCDebug(androidDeviceLog) << msg; | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  |     QMessageBox box(parent ? parent : Core::ICore::dialogParent()); | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  |     box.QDialog::setWindowTitle(dialogTitle()); | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  |     box.setText(msg); | 
					
						
							|  |  |  |     box.setIcon(icon); | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  |     box.setWindowFlag(Qt::WindowTitleHint); | 
					
						
							|  |  |  |     return box.exec(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  | bool AndroidDeviceWidget::criticalDialog(const QString &error, QWidget *parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return messageDialog(error, QMessageBox::Critical, parent); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool AndroidDeviceWidget::infoDialog(const QString &message, QWidget *parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return messageDialog(message, QMessageBox::Information, parent); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  | bool AndroidDeviceWidget::questionDialog(const QString &question, QWidget *parent) | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  |     QMessageBox box(parent ? parent : Core::ICore::dialogParent()); | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  |     box.QDialog::setWindowTitle(dialogTitle()); | 
					
						
							|  |  |  |     box.setText(question); | 
					
						
							|  |  |  |     box.setIcon(QMessageBox::Question); | 
					
						
							|  |  |  |     QPushButton *YesButton = box.addButton(QMessageBox::Yes); | 
					
						
							|  |  |  |     box.addButton(QMessageBox::No); | 
					
						
							|  |  |  |     box.setWindowFlag(Qt::WindowTitleHint); | 
					
						
							|  |  |  |     box.exec(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (box.clickedButton() == YesButton) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-26 17:41:52 +02:00
										 |  |  | AndroidDevice::AndroidDevice() | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-01-14 16:57:51 +01:00
										 |  |  |     setupId(IDevice::AutoDetected, Constants::ANDROID_DEVICE_ID); | 
					
						
							| 
									
										
										
										
											2019-01-14 16:11:27 +01:00
										 |  |  |     setType(Constants::ANDROID_DEVICE_TYPE); | 
					
						
							| 
									
										
										
										
											2020-01-21 16:17:59 +01:00
										 |  |  |     setDefaultDisplayName(tr("Run on Android")); | 
					
						
							|  |  |  |     setDisplayType(tr("Android")); | 
					
						
							| 
									
										
										
										
											2019-01-14 15:27:52 +01:00
										 |  |  |     setMachineType(IDevice::Hardware); | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |     setOsType(OsType::OsTypeOtherUnix); | 
					
						
							| 
									
										
										
										
											2022-03-05 16:59:01 +02:00
										 |  |  |     setDeviceState(DeviceDisconnected); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-26 23:06:00 +03:00
										 |  |  |     addDeviceAction({tr("Refresh"), [](const IDevice::Ptr &device, QWidget *parent) { | 
					
						
							|  |  |  |         Q_UNUSED(parent) | 
					
						
							|  |  |  |         AndroidDeviceManager::instance()->updateDeviceState(device); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  |     }}); | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  | void AndroidDevice::addActionsIfNotFound() | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  | { | 
					
						
							|  |  |  |     static const QString startAvdAction = tr("Start AVD"); | 
					
						
							|  |  |  |     static const QString eraseAvdAction = tr("Erase AVD"); | 
					
						
							|  |  |  |     static const QString avdArgumentsAction = tr("AVD Arguments"); | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  |     static const QString setupWifi = tr("Setup Wi-Fi"); | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  |     bool hasStartAction = false; | 
					
						
							|  |  |  |     bool hasEraseAction = false; | 
					
						
							|  |  |  |     bool hasAvdArgumentsAction = false; | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  |     bool hasSetupWifi = false; | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (const DeviceAction &item : deviceActions()) { | 
					
						
							|  |  |  |         if (item.display == startAvdAction) | 
					
						
							|  |  |  |             hasStartAction = true; | 
					
						
							|  |  |  |         else if (item.display == eraseAvdAction) | 
					
						
							|  |  |  |             hasEraseAction = true; | 
					
						
							|  |  |  |         else if (item.display == avdArgumentsAction) | 
					
						
							|  |  |  |             hasAvdArgumentsAction = true; | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  |         else if (item.display == setupWifi) | 
					
						
							|  |  |  |             hasSetupWifi = true; | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (machineType() == Emulator) { | 
					
						
							|  |  |  |         if (!hasStartAction) { | 
					
						
							|  |  |  |             addDeviceAction({startAvdAction, [](const IDevice::Ptr &device, QWidget *parent) { | 
					
						
							|  |  |  |                 AndroidDeviceManager::instance()->startAvd(device, parent); | 
					
						
							|  |  |  |             }}); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!hasEraseAction) { | 
					
						
							|  |  |  |             addDeviceAction({eraseAvdAction, [](const IDevice::Ptr &device, QWidget *parent) { | 
					
						
							|  |  |  |                 AndroidDeviceManager::instance()->eraseAvd(device, parent); | 
					
						
							|  |  |  |             }}); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!hasAvdArgumentsAction) { | 
					
						
							|  |  |  |             addDeviceAction({avdArgumentsAction, [](const IDevice::Ptr &device, QWidget *parent) { | 
					
						
							|  |  |  |                 Q_UNUSED(device) | 
					
						
							|  |  |  |                 AndroidDeviceManager::instance()->setEmulatorArguments(parent); | 
					
						
							|  |  |  |             }}); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  |     } else if (machineType() == Hardware && !ipRegex.match(id().toString()).hasMatch()) { | 
					
						
							|  |  |  |         if (!hasSetupWifi) { | 
					
						
							|  |  |  |             addDeviceAction({setupWifi, [](const IDevice::Ptr &device, QWidget *parent) { | 
					
						
							|  |  |  |                 AndroidDeviceManager::instance()->setupWifiForDevice(device, parent); | 
					
						
							|  |  |  |             }}); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AndroidDevice::fromMap(const QVariantMap &map) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     IDevice::fromMap(map); | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |     initAvdSettings(); | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  |     // Add Actions for Emulator and hardware if not added already.
 | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  |     // This is needed because actions for Emulators and physical devices are not the same.
 | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  |     addActionsIfNotFound(); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IDevice::Ptr AndroidDevice::create() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return IDevice::Ptr(new AndroidDevice); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AndroidDeviceInfo AndroidDevice::androidDeviceInfoFromIDevice(const IDevice *dev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     AndroidDeviceInfo info; | 
					
						
							| 
									
										
										
										
											2021-10-06 22:35:12 +03:00
										 |  |  |     info.state = dev->deviceState(); | 
					
						
							| 
									
										
										
										
											2021-10-13 21:18:13 +03:00
										 |  |  |     info.avdName = dev->extraData(Constants::AndroidAvdName).toString(); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  |     info.serialNumber = dev->extraData(Constants::AndroidSerialNumber).toString(); | 
					
						
							|  |  |  |     info.cpuAbi = dev->extraData(Constants::AndroidCpuAbi).toStringList(); | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |     const QString avdPath = dev->extraData(Constants::AndroidAvdPath).toString(); | 
					
						
							|  |  |  |     info.avdPath = FilePath::fromUserInput(avdPath); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  |     info.sdk = dev->extraData(Constants::AndroidSdk).toInt(); | 
					
						
							| 
									
										
										
										
											2021-10-06 22:35:12 +03:00
										 |  |  |     info.type = dev->machineType(); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return info; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString AndroidDevice::displayNameFromInfo(const AndroidDeviceInfo &info) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-10-06 22:35:12 +03:00
										 |  |  |     return info.type == IDevice::Hardware | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  |             ? AndroidConfigurations::currentConfig().getProductModel(info.serialNumber) | 
					
						
							| 
									
										
										
										
											2021-10-13 21:18:13 +03:00
										 |  |  |             : info.avdName; | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  | Id AndroidDevice::idFromDeviceInfo(const AndroidDeviceInfo &info) | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-10-13 21:18:13 +03:00
										 |  |  |     const QString id = (info.type == IDevice::Hardware ? info.serialNumber : info.avdName); | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |     return  Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + id); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  | Id AndroidDevice::idFromAvdInfo(const CreateAvdInfo &info) | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |     return  Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + info.name); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QStringList AndroidDevice::supportedAbis() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return extraData(Constants::AndroidCpuAbi).toStringList(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool AndroidDevice::canSupportAbis(const QStringList &abis) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // If the list is empty, no valid decision can be made, this means something is wrong
 | 
					
						
							|  |  |  |     // somewhere, but let's not stop deployment.
 | 
					
						
							|  |  |  |     QTC_ASSERT(!abis.isEmpty(), return true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QStringList ourAbis = supportedAbis(); | 
					
						
							|  |  |  |     QTC_ASSERT(!ourAbis.isEmpty(), return false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (const QString &abi : abis) | 
					
						
							|  |  |  |         if (ourAbis.contains(abi)) | 
					
						
							|  |  |  |             return true; // it's enough if only one abi match is found
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // If no exact match is found, let's take ABI backward compatibility into account
 | 
					
						
							|  |  |  |     // https://developer.android.com/ndk/guides/abis#android-platform-abi-support
 | 
					
						
							|  |  |  |     // arm64 usually can run {arm, armv7}, x86 can support {arm, armv7}, and 64-bit devices
 | 
					
						
							|  |  |  |     // can support their 32-bit variants.
 | 
					
						
							|  |  |  |     using namespace ProjectExplorer::Constants; | 
					
						
							| 
									
										
										
										
											2022-01-14 16:42:21 +01:00
										 |  |  |     const bool isTheirsArm = abis.contains(ANDROID_ABI_ARMEABI) | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  |                                 || abis.contains(ANDROID_ABI_ARMEABI_V7A); | 
					
						
							|  |  |  |     // The primary ABI at the first index
 | 
					
						
							|  |  |  |     const bool oursSupportsArm = ourAbis.first() == ANDROID_ABI_ARM64_V8A | 
					
						
							|  |  |  |                                 || ourAbis.first() == ANDROID_ABI_X86; | 
					
						
							|  |  |  |     // arm64 and x86 can run armv7 and arm
 | 
					
						
							|  |  |  |     if (isTheirsArm && oursSupportsArm) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     // x64 can run x86
 | 
					
						
							|  |  |  |     if (ourAbis.first() == ANDROID_ABI_X86_64 && abis.contains(ANDROID_ABI_X86)) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-08-16 10:17:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | bool AndroidDevice::canHandleDeployments() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // If hardware and disconned, it wouldn't be possilbe to start it, unlike an emulator
 | 
					
						
							|  |  |  |     if (machineType() == Hardware && deviceState() == DeviceDisconnected) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool AndroidDevice::isValid() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return !serialNumber().isEmpty() || !avdName().isEmpty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString AndroidDevice::serialNumber() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-21 21:40:27 +03:00
										 |  |  |     const QString serialNumber = extraData(Constants::AndroidSerialNumber).toString(); | 
					
						
							|  |  |  |     if (machineType() == Hardware) | 
					
						
							|  |  |  |         return serialNumber; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |     return AndroidDeviceManager::instance()->getRunningAvdsSerialNumber(avdName()); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString AndroidDevice::avdName() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return extraData(Constants::AndroidAvdName).toString(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int AndroidDevice::sdkLevel() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return extraData(Constants::AndroidSdk).toInt(); | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  | FilePath AndroidDevice::avdPath() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return FilePath::fromUserInput(extraData(Constants::AndroidAvdPath).toString()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AndroidDevice::setAvdPath(const FilePath &path) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     setExtraData(Constants::AndroidAvdPath, path.toUserOutput()); | 
					
						
							|  |  |  |     initAvdSettings(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  | QString AndroidDevice::androidVersion() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return AndroidManager::androidNameForApiLevel(sdkLevel()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString AndroidDevice::deviceTypeName() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (machineType() == Emulator) | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |         return tr("Emulator for \"%1\"").arg(avdSettings()->value("hw.device.name").toString()); | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  |     return tr("Physical device"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString AndroidDevice::skinName() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |     const QString skin = avdSettings()->value("skin.name").toString(); | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  |     return skin.isEmpty() ? tr("None") : skin; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString AndroidDevice::androidTargetName() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |     const QString target = avdSettings()->value("tag.display").toString(); | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  |     return target.isEmpty() ? tr("Unknown") : target; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString AndroidDevice::sdcardSize() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |     const QString size = avdSettings()->value("sdcard.size").toString(); | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  |     return size.isEmpty() ? tr("Unknown") : size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  | QString AndroidDevice::openGLStatus() const | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |     const QString openGL = avdSettings()->value("hw.gpu.enabled").toString(); | 
					
						
							|  |  |  |     return openGL.isEmpty() ? tr("Unknown") : openGL; | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-26 17:41:52 +02:00
										 |  |  | IDevice::DeviceInfo AndroidDevice::deviceInformation() const | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-26 17:41:52 +02:00
										 |  |  |     return IDevice::DeviceInfo(); | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-26 17:41:52 +02:00
										 |  |  | IDeviceWidget *AndroidDevice::createWidget() | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-19 14:54:35 +03:00
										 |  |  |     return new AndroidDeviceWidget(sharedFromThis()); | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-18 10:01:05 +02:00
										 |  |  | bool AndroidDevice::canAutoDetectPorts() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-16 15:30:30 +02:00
										 |  |  | DeviceProcessSignalOperation::Ptr AndroidDevice::signalOperation() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-30 13:20:02 +02:00
										 |  |  |     return DeviceProcessSignalOperation::Ptr(new AndroidSignalOperation()); | 
					
						
							| 
									
										
										
										
											2013-09-16 15:30:30 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-29 18:32:01 +02:00
										 |  |  | QUrl AndroidDevice::toolControlChannel(const ControlChannelHint &) const | 
					
						
							| 
									
										
										
										
											2013-10-11 12:58:24 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-06-29 18:32:01 +02:00
										 |  |  |     QUrl url; | 
					
						
							| 
									
										
										
										
											2022-04-05 17:11:05 +02:00
										 |  |  |     url.setScheme(urlTcpScheme()); | 
					
						
							| 
									
										
										
										
											2017-06-29 18:32:01 +02:00
										 |  |  |     url.setHost("localhost"); | 
					
						
							|  |  |  |     return url; | 
					
						
							| 
									
										
										
										
											2013-10-11 12:58:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  | QSettings *AndroidDevice::avdSettings() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return m_avdSettings.get(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AndroidDevice::initAvdSettings() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const FilePath configPath = avdPath().resolvePath(QStringLiteral("config.ini")); | 
					
						
							|  |  |  |     m_avdSettings.reset(new QSettings(configPath.toUserOutput(), QSettings::IniFormat)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  | void AndroidDeviceManager::updateAvdsList() | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |     if (!m_avdsFutureWatcher.isRunning() && m_androidConfig.adbToolPath().exists()) | 
					
						
							|  |  |  |         m_avdsFutureWatcher.setFuture(m_avdManager.avdList()); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  | IDevice::DeviceState AndroidDeviceManager::getDeviceState(const QString &serial, | 
					
						
							|  |  |  |                                                           IDevice::MachineType type) const | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |     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; | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-02-20 19:13:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  | void AndroidDeviceManager::updateDeviceState(const ProjectExplorer::IDevice::ConstPtr &device) | 
					
						
							| 
									
										
										
										
											2021-09-26 23:06:00 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |     const AndroidDevice *dev = static_cast<const AndroidDevice *>(device.data()); | 
					
						
							| 
									
										
										
										
											2021-09-26 23:06:00 +03:00
										 |  |  |     const QString serial = dev->serialNumber(); | 
					
						
							|  |  |  |     DeviceManager *const devMgr = DeviceManager::instance(); | 
					
						
							| 
									
										
										
										
											2022-04-05 17:11:05 +02:00
										 |  |  |     const Id id = dev->id(); | 
					
						
							| 
									
										
										
										
											2022-03-05 16:59:01 +02:00
										 |  |  |     if (!serial.isEmpty()) | 
					
						
							|  |  |  |         devMgr->setDeviceState(id, getDeviceState(serial, dev->machineType())); | 
					
						
							|  |  |  |     else if (dev->machineType() == IDevice::Emulator) | 
					
						
							| 
									
										
										
										
											2021-09-26 23:06:00 +03:00
										 |  |  |         devMgr->setDeviceState(id, IDevice::DeviceConnected); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  | void AndroidDeviceManager::startAvd(const ProjectExplorer::IDevice::Ptr &device, QWidget *parent) | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  |     Q_UNUSED(parent) | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  |     const AndroidDevice *androidDev = static_cast<const AndroidDevice *>(device.data()); | 
					
						
							|  |  |  |     const QString name = androidDev->avdName(); | 
					
						
							|  |  |  |     qCDebug(androidDeviceLog, "Starting Android AVD id \"%s\".", qPrintable(name)); | 
					
						
							| 
									
										
										
										
											2022-04-05 17:11:05 +02:00
										 |  |  |     runAsync([this, name, device]() { | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  |         const QString serialNumber = m_avdManager.startAvd(name); | 
					
						
							|  |  |  |         // Mark the AVD as ReadyToUse once we know it's started
 | 
					
						
							|  |  |  |         if (!serialNumber.isEmpty()) { | 
					
						
							|  |  |  |             DeviceManager *const devMgr = DeviceManager::instance(); | 
					
						
							|  |  |  |             devMgr->setDeviceState(device->id(), IDevice::DeviceReadyToUse); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  | void AndroidDeviceManager::eraseAvd(const IDevice::Ptr &device, QWidget *parent) | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | { | 
					
						
							|  |  |  |     if (device.isNull()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (device->machineType() == IDevice::Hardware) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QString name = static_cast<const AndroidDevice *>(device.data())->avdName(); | 
					
						
							| 
									
										
										
										
											2021-10-28 10:03:28 +02:00
										 |  |  |     const QString question | 
					
						
							|  |  |  |         = AndroidDevice::tr("Erase the Android AVD \"%1\"?\nThis cannot be undone.").arg(name); | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  |     if (!AndroidDeviceWidget::questionDialog(question, parent)) | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     qCDebug(androidDeviceLog) << QString("Erasing Android AVD \"%1\" from the system.").arg(name); | 
					
						
							| 
									
										
										
										
											2022-04-05 17:11:05 +02:00
										 |  |  |     m_removeAvdFutureWatcher.setFuture(runAsync([this, name, device]() { | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  |         QPair<IDevice::ConstPtr, bool> pair; | 
					
						
							|  |  |  |         pair.first = device; | 
					
						
							|  |  |  |         pair.second = false; | 
					
						
							|  |  |  |         if (m_avdManager.removeAvd(name)) | 
					
						
							|  |  |  |             pair.second = true; | 
					
						
							|  |  |  |         return pair; | 
					
						
							|  |  |  |     })); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  | void AndroidDeviceManager::setupWifiForDevice(const IDevice::Ptr &device, QWidget *parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (device->deviceState() != IDevice::DeviceReadyToUse) { | 
					
						
							|  |  |  |         AndroidDeviceWidget::infoDialog( | 
					
						
							|  |  |  |                     AndroidDevice::tr("The device has to be connected with ADB debugging " | 
					
						
							|  |  |  |                                       "enabled to use this feature."), parent); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const auto androidDev = static_cast<const AndroidDevice *>(device.data()); | 
					
						
							|  |  |  |     const QStringList adbSelector = AndroidDeviceInfo::adbSelector(androidDev->serialNumber()); | 
					
						
							|  |  |  |     // prepare port
 | 
					
						
							|  |  |  |     QStringList args = adbSelector; | 
					
						
							|  |  |  |     args.append({"tcpip", wifiDevicePort}); | 
					
						
							|  |  |  |     const SdkToolResult result = AndroidManager::runAdbCommand(args); | 
					
						
							|  |  |  |     if (!result.success()) { | 
					
						
							|  |  |  |         AndroidDeviceWidget::criticalDialog( | 
					
						
							|  |  |  |                     AndroidDevice::tr("Opening connection port %1 failed.").arg(wifiDevicePort), | 
					
						
							|  |  |  |                     parent); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTimer::singleShot(2000, parent, [adbSelector, &parent]() { | 
					
						
							|  |  |  |         // Get device IP address
 | 
					
						
							|  |  |  |         QStringList args = adbSelector; | 
					
						
							|  |  |  |         args.append({"shell", "ip", "route"}); | 
					
						
							|  |  |  |         const SdkToolResult ipRes = AndroidManager::runAdbCommand(args); | 
					
						
							|  |  |  |         if (!ipRes.success()) { | 
					
						
							|  |  |  |             AndroidDeviceWidget::criticalDialog( | 
					
						
							|  |  |  |                         AndroidDevice::tr("Retrieving the device IP address failed."), parent); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Expected output from "ip route" is:
 | 
					
						
							|  |  |  |         // 192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.190
 | 
					
						
							|  |  |  |         // where the ip of interest is at the end of the line
 | 
					
						
							|  |  |  |         const QStringList ipParts = ipRes.stdOut().split(" "); | 
					
						
							|  |  |  |         QString ip; | 
					
						
							|  |  |  |         if (!ipParts.isEmpty()) { | 
					
						
							|  |  |  |             ip = ipParts.last(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!ipRegex.match(ipParts.last()).hasMatch()) { | 
					
						
							|  |  |  |             AndroidDeviceWidget::criticalDialog( | 
					
						
							|  |  |  |                         AndroidDevice::tr("The retrieved IP address is invalid."), parent); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Connect to device
 | 
					
						
							|  |  |  |         args = adbSelector; | 
					
						
							|  |  |  |         args.append({"connect", QString("%1:%2").arg(ip).arg(wifiDevicePort)}); | 
					
						
							|  |  |  |         const SdkToolResult connectRes = AndroidManager::runAdbCommand(args); | 
					
						
							|  |  |  |         if (!connectRes.success()) { | 
					
						
							|  |  |  |             AndroidDeviceWidget::criticalDialog( | 
					
						
							|  |  |  |                         AndroidDevice::tr("Connecting to to the device IP \"%1\" failed.").arg(ip), | 
					
						
							|  |  |  |                         parent); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | void AndroidDeviceManager::handleAvdRemoved() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QPair<IDevice::ConstPtr, bool> result = m_removeAvdFutureWatcher.result(); | 
					
						
							|  |  |  |     const QString name = result.first->displayName(); | 
					
						
							|  |  |  |     if (result.second) { | 
					
						
							|  |  |  |         qCDebug(androidDeviceLog, "Android AVD id \"%s\" removed from the system.", qPrintable(name)); | 
					
						
							|  |  |  |         // Remove the device from QtC after it's been removed using avdmanager.
 | 
					
						
							|  |  |  |         DeviceManager::instance()->removeDevice(result.first->id()); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         AndroidDeviceWidget::criticalDialog(QObject::tr("An error occurred while removing the " | 
					
						
							|  |  |  |                 "Android AVD \"%1\" using avdmanager tool.").arg(name)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  | QString AndroidDeviceManager::emulatorName(const QString &serialNumber) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QStringList args = AndroidDeviceInfo::adbSelector(serialNumber); | 
					
						
							|  |  |  |     args.append({"emu", "avd", "name"}); | 
					
						
							|  |  |  |     return AndroidManager::runAdbCommand(args).stdOut(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  | void AndroidDeviceManager::setEmulatorArguments(QWidget *parent) | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | { | 
					
						
							|  |  |  |     const QString helpUrl = | 
					
						
							|  |  |  |             "https://developer.android.com/studio/run/emulator-commandline#startup-options"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 21:19:00 +03:00
										 |  |  |     QInputDialog dialog(parent ? parent : Core::ICore::dialogParent()); | 
					
						
							| 
									
										
										
										
											2021-10-28 10:03:28 +02:00
										 |  |  |     dialog.setWindowTitle(AndroidDevice::tr("Emulator Command-line Startup Options")); | 
					
						
							|  |  |  |     dialog.setLabelText(AndroidDevice::tr("Emulator command-line startup options " | 
					
						
							|  |  |  |                                           "(<a href=\"%1\">Help Web Page</a>):") | 
					
						
							|  |  |  |                             .arg(helpUrl)); | 
					
						
							| 
									
										
										
										
											2022-04-14 16:52:51 +02:00
										 |  |  |     dialog.setTextValue(m_androidConfig.emulatorArgs()); | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (auto label = dialog.findChild<QLabel*>()) { | 
					
						
							|  |  |  |         label->setOpenExternalLinks(true); | 
					
						
							|  |  |  |         label->setMinimumWidth(500); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (dialog.exec() != QDialog::Accepted) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-14 16:52:51 +02:00
										 |  |  |     m_androidConfig.setEmulatorArgs(dialog.textValue()); | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  | QString AndroidDeviceManager::getRunningAvdsSerialNumber(const QString &name) const | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |     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; | 
					
						
							| 
									
										
										
										
											2021-11-10 22:38:59 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  | void AndroidDeviceManager::setupDevicesWatcher() | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |     if (!m_androidConfig.adbToolPath().exists()) { | 
					
						
							|  |  |  |         qCDebug(androidDeviceLog) << "Cannot start ADB device watcher" | 
					
						
							|  |  |  |                                   <<  "because adb path does not exist."; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |     if (!m_adbDeviceWatcherProcess) | 
					
						
							| 
									
										
										
										
											2022-04-05 17:11:05 +02:00
										 |  |  |         m_adbDeviceWatcherProcess.reset(new QtcProcess(this)); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |     if (m_adbDeviceWatcherProcess->isRunning()) { | 
					
						
							|  |  |  |         qCDebug(androidDeviceLog) << "ADB device watcher is already running."; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-05 17:11:05 +02:00
										 |  |  |     connect(m_adbDeviceWatcherProcess.get(), &QtcProcess::done, this, [this] { | 
					
						
							|  |  |  |         if (m_adbDeviceWatcherProcess->error() != QProcess::UnknownError) { | 
					
						
							|  |  |  |             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(), &QtcProcess::start); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-04-05 17:11:05 +02:00
										 |  |  |         qCDebug(androidDeviceLog) << "ADB device watcher finished."; | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_adbDeviceWatcherProcess->setStdErrLineCallback([](const QString &error) { | 
					
						
							|  |  |  |         qCDebug(androidDeviceLog) << "ADB device watcher error" << error; }); | 
					
						
							|  |  |  |     m_adbDeviceWatcherProcess->setStdOutLineCallback([this](const QString &output) { | 
					
						
							|  |  |  |         HandleDevicesListChange(output); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-05 17:11:05 +02:00
										 |  |  |     const CommandLine command = CommandLine(m_androidConfig.adbToolPath(), {"track-devices"}); | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |     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"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-05 17:11:05 +02:00
										 |  |  |     const FilePath avdPath = FilePath::fromUserInput(avdEnvVar); | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |     m_avdFileSystemWatcher.addPath(avdPath.toString()); | 
					
						
							|  |  |  |     connect(&m_avdsFutureWatcher, &QFutureWatcherBase::finished, | 
					
						
							|  |  |  |             this,  &AndroidDeviceManager::HandleAvdsListChange); | 
					
						
							| 
									
										
										
										
											2022-07-19 22:51:32 +02:00
										 |  |  |     connect(&m_avdFileSystemWatcher, &QFileSystemWatcher::directoryChanged, this, [this] { | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |         // If the avd list upate command is running no need to call it again.
 | 
					
						
							|  |  |  |         if (!m_avdsFutureWatcher.isRunning()) | 
					
						
							|  |  |  |             updateAvdsList(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     // Call initial update
 | 
					
						
							|  |  |  |     updateAvdsList(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  | void AndroidDeviceManager::HandleAvdsListChange() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     DeviceManager *const devMgr = DeviceManager::instance(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |     QVector<Id> existingAvds; | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  |     for (int i = 0; i < devMgr->deviceCount(); ++i) { | 
					
						
							|  |  |  |         const IDevice::ConstPtr dev = devMgr->deviceAt(i); | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |         const bool isEmulator = dev->machineType() == IDevice::Emulator; | 
					
						
							|  |  |  |         if (isEmulator && dev->type() == Constants::ANDROID_DEVICE_TYPE) | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |             existingAvds.append(dev->id()); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |     QVector<Id> connectedDevs; | 
					
						
							| 
									
										
										
										
											2022-02-28 14:46:58 +01:00
										 |  |  |     for (const AndroidDeviceInfo &item : m_avdsFutureWatcher.result()) { | 
					
						
							| 
									
										
										
										
											2022-04-05 17:11:05 +02:00
										 |  |  |         const Id deviceId = AndroidDevice::idFromDeviceInfo(item); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  |         const QString displayName = AndroidDevice::displayNameFromInfo(item); | 
					
						
							|  |  |  |         IDevice::ConstPtr dev = devMgr->find(deviceId); | 
					
						
							|  |  |  |         if (!dev.isNull()) { | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |             const auto androidDev = static_cast<const AndroidDevice *>(dev.data()); | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |             // DeviceManager doens't seem to have a way to directly update the name, if the name
 | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |             // 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
 | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |             // invalid data by checking if the avdPath is not empty.
 | 
					
						
							|  |  |  |             if (dev->displayName() != displayName || androidDev->avdPath().toString().isEmpty()) { | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |                 devMgr->removeDevice(dev->id()); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 // Find the state of the AVD retrieved from the AVD watcher
 | 
					
						
							| 
									
										
										
										
											2021-10-13 21:18:13 +03:00
										 |  |  |                 const QString serial = getRunningAvdsSerialNumber(item.avdName); | 
					
						
							| 
									
										
										
										
											2022-03-05 16:59:01 +02:00
										 |  |  |                 if (!serial.isEmpty()) { | 
					
						
							|  |  |  |                     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()); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     devMgr->setDeviceState(dev->id(), IDevice::DeviceConnected); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |                 connectedDevs.append(dev->id()); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-02-20 19:13:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  |         AndroidDevice *newDev = new AndroidDevice(); | 
					
						
							|  |  |  |         newDev->setupId(IDevice::AutoDetected, deviceId); | 
					
						
							|  |  |  |         newDev->setDisplayName(displayName); | 
					
						
							| 
									
										
										
										
											2021-10-06 22:35:12 +03:00
										 |  |  |         newDev->setMachineType(item.type); | 
					
						
							|  |  |  |         newDev->setDeviceState(item.state); | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-13 21:18:13 +03:00
										 |  |  |         newDev->setExtraData(Constants::AndroidAvdName, item.avdName); | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |         newDev->setExtraData(Constants::AndroidSerialNumber, item.serialNumber); | 
					
						
							|  |  |  |         newDev->setExtraData(Constants::AndroidCpuAbi, item.cpuAbi); | 
					
						
							|  |  |  |         newDev->setExtraData(Constants::AndroidSdk, item.sdk); | 
					
						
							|  |  |  |         newDev->setAvdPath(item.avdPath); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  |         qCDebug(androidDeviceLog, "Registering new Android device id \"%s\".", | 
					
						
							|  |  |  |                 newDev->id().toString().toUtf8().data()); | 
					
						
							|  |  |  |         const IDevice::ConstPtr constNewDev = IDevice::ConstPtr(newDev); | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |         devMgr->addDevice(IDevice::ConstPtr(constNewDev)); | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |         connectedDevs.append(constNewDev->id()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |     // Set devices no longer connected to disconnected state.
 | 
					
						
							|  |  |  |     for (const Id &id : existingAvds) { | 
					
						
							|  |  |  |         if (!connectedDevs.contains(id)) { | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |                 qCDebug(androidDeviceLog, "Removing AVD id \"%s\" because it no longer exists.", | 
					
						
							| 
									
										
										
										
											2021-10-13 21:16:47 +03:00
										 |  |  |                         id.toString().toUtf8().data()); | 
					
						
							|  |  |  |                 devMgr->removeDevice(id); | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  | 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); | 
					
						
							| 
									
										
										
										
											2022-04-05 17:11:05 +02:00
										 |  |  |         const Id avdId = Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + avdName); | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |         devMgr->setDeviceState(avdId, state); | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2022-04-05 17:11:05 +02:00
										 |  |  |         const Id id = Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + serial); | 
					
						
							| 
									
										
										
										
											2022-02-22 21:31:12 +02:00
										 |  |  |         QString displayName = AndroidConfigurations::currentConfig().getProductModel(serial); | 
					
						
							|  |  |  |         // Check if the device is connected via WiFi. A sample serial of such devices can be
 | 
					
						
							|  |  |  |         // like: "192.168.1.190:5555"
 | 
					
						
							| 
									
										
										
										
											2022-03-06 00:06:27 +02:00
										 |  |  |         static const auto ipRegex = QRegularExpression(ipRegexStr + QStringLiteral(":(\\d{1,5})")); | 
					
						
							|  |  |  |         if (ipRegex.match(serial).hasMatch()) | 
					
						
							| 
									
										
										
										
											2022-02-22 21:31:12 +02:00
										 |  |  |             displayName += QLatin1String(" (WiFi)"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 18:19:54 +03:00
										 |  |  |         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)); | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-14 22:12:21 +01:00
										 |  |  | static AndroidDeviceManager *s_instance = nullptr; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | AndroidDeviceManager *AndroidDeviceManager::instance() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-03-14 22:12:21 +01:00
										 |  |  |     return s_instance; | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AndroidDeviceManager::AndroidDeviceManager(QObject *parent) | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  |     : QObject(parent), | 
					
						
							| 
									
										
										
										
											2021-10-25 15:58:02 +03:00
										 |  |  |       m_androidConfig(AndroidConfigurations::currentConfig()), | 
					
						
							|  |  |  |       m_avdManager(m_androidConfig) | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  |     connect(&m_removeAvdFutureWatcher, &QFutureWatcherBase::finished, | 
					
						
							|  |  |  |             this, &AndroidDeviceManager::handleAvdRemoved); | 
					
						
							| 
									
										
										
										
											2022-03-14 22:12:21 +01:00
										 |  |  |     QTC_ASSERT(!s_instance, return); | 
					
						
							|  |  |  |     s_instance = this; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AndroidDeviceManager::~AndroidDeviceManager() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_avdsFutureWatcher.waitForFinished(); | 
					
						
							|  |  |  |     m_removeAvdFutureWatcher.waitForFinished(); | 
					
						
							|  |  |  |     QTC_ASSERT(s_instance == this, return); | 
					
						
							|  |  |  |     s_instance = nullptr; | 
					
						
							| 
									
										
										
										
											2021-08-22 01:51:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Factory
 | 
					
						
							| 
									
										
										
										
											2022-01-26 09:05:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-20 19:13:28 +01:00
										 |  |  | AndroidDeviceFactory::AndroidDeviceFactory() | 
					
						
							| 
									
										
										
										
											2022-01-26 09:05:35 +01:00
										 |  |  |     : IDeviceFactory(Constants::ANDROID_DEVICE_TYPE), | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  |       m_androidConfig(AndroidConfigurations::currentConfig()) | 
					
						
							| 
									
										
										
										
											2019-02-20 19:13:28 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-10-25 12:56:52 +03:00
										 |  |  |     setDisplayName(AndroidDevice::tr("Android Device")); | 
					
						
							| 
									
										
										
										
											2019-02-20 19:13:28 +01:00
										 |  |  |     setCombinedIcon(":/android/images/androiddevicesmall.png", | 
					
						
							|  |  |  |                     ":/android/images/androiddevice.png"); | 
					
						
							| 
									
										
										
										
											2022-01-26 09:05:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-20 19:13:28 +01:00
										 |  |  |     setConstructionFunction(&AndroidDevice::create); | 
					
						
							| 
									
										
										
										
											2022-01-26 10:00:24 +01:00
										 |  |  |     if (m_androidConfig.sdkToolsOk()) { | 
					
						
							|  |  |  |         setCreator([this] { | 
					
						
							|  |  |  |             AvdDialog dialog = AvdDialog(m_androidConfig, Core::ICore::dialogParent()); | 
					
						
							|  |  |  |             if (dialog.exec() != QDialog::Accepted) | 
					
						
							|  |  |  |                 return IDevice::Ptr(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const IDevice::Ptr dev = dialog.device(); | 
					
						
							|  |  |  |             if (const auto androidDev = static_cast<AndroidDevice *>(dev.data())) { | 
					
						
							|  |  |  |                 qCDebug(androidDeviceLog, "Created new Android AVD id \"%s\".", | 
					
						
							|  |  |  |                         qPrintable(androidDev->avdName())); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 AndroidDeviceWidget::criticalDialog( | 
					
						
							|  |  |  |                         AndroidDevice::tr("The device info returned from AvdDialog is invalid.")); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-09-11 18:38:13 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-26 10:00:24 +01:00
										 |  |  |             return IDevice::Ptr(dev); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-02-20 19:13:28 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-03 16:57:44 +03:00
										 |  |  | } // namespace Internal
 | 
					
						
							|  |  |  | } // namespace Android
 |