forked from qt-creator/qt-creator
Android: Make avd output parsing testable
And add some tests Change-Id: Ife0e0c60f55251a1ac23215055ece8fb01478d59 Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -14,6 +14,7 @@ add_qtc_plugin(Android
|
|||||||
androiddeployqtstep.cpp androiddeployqtstep.h
|
androiddeployqtstep.cpp androiddeployqtstep.h
|
||||||
androiddevice.cpp androiddevice.h
|
androiddevice.cpp androiddevice.h
|
||||||
androiddevicedialog.cpp androiddevicedialog.h androiddevicedialog.ui
|
androiddevicedialog.cpp androiddevicedialog.h androiddevicedialog.ui
|
||||||
|
androiddeviceinfo.cpp androiddeviceinfo.h
|
||||||
androiderrormessage.cpp androiderrormessage.h
|
androiderrormessage.cpp androiderrormessage.h
|
||||||
androidextralibrarylistmodel.cpp androidextralibrarylistmodel.h
|
androidextralibrarylistmodel.cpp androidextralibrarylistmodel.h
|
||||||
androidglobal.h
|
androidglobal.h
|
||||||
@@ -43,6 +44,7 @@ add_qtc_plugin(Android
|
|||||||
androidsignaloperation.cpp androidsignaloperation.h
|
androidsignaloperation.cpp androidsignaloperation.h
|
||||||
androidtoolchain.cpp androidtoolchain.h
|
androidtoolchain.cpp androidtoolchain.h
|
||||||
avddialog.cpp avddialog.h
|
avddialog.cpp avddialog.h
|
||||||
|
avdmanageroutputparser.cpp avdmanageroutputparser.h
|
||||||
certificatesmodel.cpp certificatesmodel.h
|
certificatesmodel.cpp certificatesmodel.h
|
||||||
createandroidmanifestwizard.cpp createandroidmanifestwizard.h
|
createandroidmanifestwizard.cpp createandroidmanifestwizard.h
|
||||||
javaeditor.cpp javaeditor.h
|
javaeditor.cpp javaeditor.h
|
||||||
|
@@ -27,6 +27,7 @@ HEADERS += \
|
|||||||
javaparser.h \
|
javaparser.h \
|
||||||
androidplugin.h \
|
androidplugin.h \
|
||||||
androiddevice.h \
|
androiddevice.h \
|
||||||
|
androiddeviceinfo.h \
|
||||||
androidqmltoolingsupport.h \
|
androidqmltoolingsupport.h \
|
||||||
androidmanifesteditorfactory.h \
|
androidmanifesteditorfactory.h \
|
||||||
androidmanifesteditor.h \
|
androidmanifesteditor.h \
|
||||||
@@ -40,6 +41,7 @@ HEADERS += \
|
|||||||
javaeditor.h \
|
javaeditor.h \
|
||||||
javaindenter.h \
|
javaindenter.h \
|
||||||
avddialog.h \
|
avddialog.h \
|
||||||
|
avdmanageroutputparser.h \
|
||||||
android_global.h \
|
android_global.h \
|
||||||
androidbuildapkstep.h \
|
androidbuildapkstep.h \
|
||||||
androidsdkmanager.h \
|
androidsdkmanager.h \
|
||||||
@@ -74,6 +76,7 @@ SOURCES += \
|
|||||||
javaparser.cpp \
|
javaparser.cpp \
|
||||||
androidplugin.cpp \
|
androidplugin.cpp \
|
||||||
androiddevice.cpp \
|
androiddevice.cpp \
|
||||||
|
androiddeviceinfo.cpp \
|
||||||
androidqmltoolingsupport.cpp \
|
androidqmltoolingsupport.cpp \
|
||||||
androidmanifesteditorfactory.cpp \
|
androidmanifesteditorfactory.cpp \
|
||||||
androidmanifesteditor.cpp \
|
androidmanifesteditor.cpp \
|
||||||
@@ -87,6 +90,7 @@ SOURCES += \
|
|||||||
javaeditor.cpp \
|
javaeditor.cpp \
|
||||||
javaindenter.cpp \
|
javaindenter.cpp \
|
||||||
avddialog.cpp \
|
avddialog.cpp \
|
||||||
|
avdmanageroutputparser.cpp \
|
||||||
androidbuildapkstep.cpp \
|
androidbuildapkstep.cpp \
|
||||||
androidsdkmanager.cpp \
|
androidsdkmanager.cpp \
|
||||||
androidavdmanager.cpp \
|
androidavdmanager.cpp \
|
||||||
|
@@ -40,6 +40,8 @@ Project {
|
|||||||
"androiddevicedialog.ui",
|
"androiddevicedialog.ui",
|
||||||
"androiddevice.cpp",
|
"androiddevice.cpp",
|
||||||
"androiddevice.h",
|
"androiddevice.h",
|
||||||
|
"androiddeviceinfo.cpp",
|
||||||
|
"androiddeviceinfo.h",
|
||||||
"androiderrormessage.h",
|
"androiderrormessage.h",
|
||||||
"androiderrormessage.cpp",
|
"androiderrormessage.cpp",
|
||||||
"androidextralibrarylistmodel.cpp",
|
"androidextralibrarylistmodel.cpp",
|
||||||
@@ -100,6 +102,8 @@ Project {
|
|||||||
"androidtoolchain.h",
|
"androidtoolchain.h",
|
||||||
"avddialog.cpp",
|
"avddialog.cpp",
|
||||||
"avddialog.h",
|
"avddialog.h",
|
||||||
|
"avdmanageroutputparser.cpp",
|
||||||
|
"avdmanageroutputparser.h",
|
||||||
"certificatesmodel.cpp",
|
"certificatesmodel.cpp",
|
||||||
"certificatesmodel.h",
|
"certificatesmodel.h",
|
||||||
"createandroidmanifestwizard.h",
|
"createandroidmanifestwizard.h",
|
||||||
|
@@ -24,6 +24,8 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include "androidavdmanager.h"
|
#include "androidavdmanager.h"
|
||||||
|
|
||||||
|
#include "avdmanageroutputparser.h"
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
@@ -51,17 +53,6 @@ namespace Internal {
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
// Avd list keys to parse avd
|
|
||||||
const char avdInfoNameKey[] = "Name:";
|
|
||||||
const char avdInfoPathKey[] = "Path:";
|
|
||||||
const char avdInfoAbiKey[] = "abi.type";
|
|
||||||
const char avdInfoTargetKey[] = "target";
|
|
||||||
const char avdInfoErrorKey[] = "Error:";
|
|
||||||
const char avdInfoSdcardKey[] = "Sdcard";
|
|
||||||
const char avdInfoTargetTypeKey[] = "Target";
|
|
||||||
const char avdInfoDeviceKey[] = "Device";
|
|
||||||
const char avdInfoSkinKey[] = "Skin";
|
|
||||||
|
|
||||||
const int avdCreateTimeoutMs = 30000;
|
const int avdCreateTimeoutMs = 30000;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -85,21 +76,6 @@ bool AndroidAvdManager::avdManagerCommand(const AndroidConfig &config, const QSt
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
Parses the \a line for a [spaces]key[spaces]value[spaces] pattern and returns
|
|
||||||
\c true if the key is found, \c false otherwise. The value is copied into \a value.
|
|
||||||
*/
|
|
||||||
static bool valueForKey(QString key, const QString &line, QString *value = nullptr)
|
|
||||||
{
|
|
||||||
auto trimmedInput = line.trimmed();
|
|
||||||
if (trimmedInput.startsWith(key)) {
|
|
||||||
if (value)
|
|
||||||
*value = trimmedInput.section(key, 1, 1).trimmed();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool checkForTimeout(const chrono::steady_clock::time_point &start,
|
static bool checkForTimeout(const chrono::steady_clock::time_point &start,
|
||||||
int msecs = 3000)
|
int msecs = 3000)
|
||||||
{
|
{
|
||||||
@@ -203,25 +179,8 @@ static void avdProcessFinished(int exitCode, QProcess *p)
|
|||||||
p->deleteLater();
|
p->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
AndroidAvdManager::AndroidAvdManager(const AndroidConfig &config)
|
||||||
\class AvdManagerOutputParser
|
: m_config(config)
|
||||||
\brief The AvdManagerOutputParser class is a helper class to parse the output of the avdmanager
|
|
||||||
commands.
|
|
||||||
*/
|
|
||||||
class AvdManagerOutputParser
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AndroidDeviceInfoList listVirtualDevices(const AndroidConfig &config);
|
|
||||||
AndroidDeviceInfoList parseAvdList(const QString &output);
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool parseAvd(const QStringList &deviceInfo, AndroidDeviceInfo *avd);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
AndroidAvdManager::AndroidAvdManager(const AndroidConfig &config):
|
|
||||||
m_config(config),
|
|
||||||
m_parser(new AvdManagerOutputParser)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -243,9 +202,69 @@ bool AndroidAvdManager::removeAvd(const QString &name) const
|
|||||||
return response.result == Utils::SynchronousProcessResponse::Finished && response.exitCode == 0;
|
return response.result == Utils::SynchronousProcessResponse::Finished && response.exitCode == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void avdConfigEditManufacturerTag(const QString &avdPathStr, bool recoverMode = false)
|
||||||
|
{
|
||||||
|
const Utils::FilePath avdPath = Utils::FilePath::fromString(avdPathStr);
|
||||||
|
if (avdPath.exists()) {
|
||||||
|
const QString configFilePath = avdPath.pathAppended("config.ini").toString();
|
||||||
|
QFile configFile(configFilePath);
|
||||||
|
if (configFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
||||||
|
QString newContent;
|
||||||
|
QTextStream textStream(&configFile);
|
||||||
|
while (!textStream.atEnd()) {
|
||||||
|
QString line = textStream.readLine();
|
||||||
|
if (!line.contains("hw.device.manufacturer"))
|
||||||
|
newContent.append(line + "\n");
|
||||||
|
else if (recoverMode)
|
||||||
|
newContent.append(line.replace("#", "") + "\n");
|
||||||
|
else
|
||||||
|
newContent.append("#" + line + "\n");
|
||||||
|
}
|
||||||
|
configFile.resize(0);
|
||||||
|
textStream << newContent;
|
||||||
|
configFile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static AndroidDeviceInfoList listVirtualDevices(const AndroidConfig &config)
|
||||||
|
{
|
||||||
|
QString output;
|
||||||
|
AndroidDeviceInfoList avdList;
|
||||||
|
/*
|
||||||
|
Currenly avdmanager tool fails to parse some AVDs because the correct
|
||||||
|
device definitions at devices.xml does not have some of the newest devices.
|
||||||
|
Particularly, failing because of tag "hw.device.manufacturer", thus removing
|
||||||
|
it would make paring successful. However, it has to be returned afterwards,
|
||||||
|
otherwise, Android Studio would give an error during parsing also. So this fix
|
||||||
|
aim to keep support for Qt Creator and Android Studio.
|
||||||
|
*/
|
||||||
|
QStringList allAvdErrorPaths;
|
||||||
|
QStringList avdErrorPaths;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!AndroidAvdManager::avdManagerCommand(config, {"list", "avd"}, &output)) {
|
||||||
|
qCDebug(avdManagerLog)
|
||||||
|
<< "Avd list command failed" << output << config.sdkToolsVersion();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
avdErrorPaths.clear();
|
||||||
|
avdList = parseAvdList(output, &avdErrorPaths);
|
||||||
|
allAvdErrorPaths << avdErrorPaths;
|
||||||
|
for (const QString &avdPathStr : qAsConst(avdErrorPaths))
|
||||||
|
avdConfigEditManufacturerTag(avdPathStr); // comment out manufacturer tag
|
||||||
|
} while (!avdErrorPaths.isEmpty()); // try again
|
||||||
|
|
||||||
|
for (const QString &avdPathStr : qAsConst(allAvdErrorPaths))
|
||||||
|
avdConfigEditManufacturerTag(avdPathStr, true); // re-add manufacturer tag
|
||||||
|
|
||||||
|
return avdList;
|
||||||
|
}
|
||||||
|
|
||||||
QFuture<AndroidDeviceInfoList> AndroidAvdManager::avdList() const
|
QFuture<AndroidDeviceInfoList> AndroidAvdManager::avdList() const
|
||||||
{
|
{
|
||||||
return Utils::runAsync(&AvdManagerOutputParser::listVirtualDevices, m_parser.get(), m_config);
|
return Utils::runAsync(listVirtualDevices, m_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AndroidAvdManager::startAvd(const QString &name) const
|
QString AndroidAvdManager::startAvd(const QString &name) const
|
||||||
@@ -353,147 +372,7 @@ bool AndroidAvdManager::waitForBooted(const QString &serialNumber,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Currenly avdmanager tool fails to parse some AVDs because the correct
|
|
||||||
* device definitions at devices.xml does not have some of the newest devices.
|
|
||||||
* Particularly, failing because of tag "hw.device.manufacturer", thus removing
|
|
||||||
* it would make paring successful. However, it has to be returned afterwards,
|
|
||||||
* otherwise, Android Studio would give an error during parsing also. So this fix
|
|
||||||
* aim to keep support for Qt Creator and Android Studio.
|
|
||||||
*/
|
|
||||||
static const QString avdManufacturerError = "no longer exists as a device";
|
|
||||||
static QStringList avdErrorPaths;
|
static QStringList avdErrorPaths;
|
||||||
|
|
||||||
static void AvdConfigEditManufacturerTag(const QString &avdPathStr, bool recoverMode = false)
|
|
||||||
{
|
|
||||||
const Utils::FilePath avdPath = Utils::FilePath::fromString(avdPathStr);
|
|
||||||
if (avdPath.exists()) {
|
|
||||||
const QString configFilePath = avdPath.pathAppended("config.ini").toString();
|
|
||||||
QFile configFile(configFilePath);
|
|
||||||
if (configFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
|
||||||
QString newContent;
|
|
||||||
QTextStream textStream(&configFile);
|
|
||||||
while (!textStream.atEnd()) {
|
|
||||||
QString line = textStream.readLine();
|
|
||||||
if (!line.contains("hw.device.manufacturer"))
|
|
||||||
newContent.append(line + "\n");
|
|
||||||
else if (recoverMode)
|
|
||||||
newContent.append(line.replace("#", "") + "\n");
|
|
||||||
else
|
|
||||||
newContent.append("#" + line + "\n");
|
|
||||||
}
|
|
||||||
configFile.resize(0);
|
|
||||||
textStream << newContent;
|
|
||||||
configFile.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AndroidDeviceInfoList AvdManagerOutputParser::listVirtualDevices(const AndroidConfig &config)
|
|
||||||
{
|
|
||||||
QString output;
|
|
||||||
AndroidDeviceInfoList avdList;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (!AndroidAvdManager::avdManagerCommand(config, {"list", "avd"}, &output)) {
|
|
||||||
qCDebug(avdManagerLog)
|
|
||||||
<< "Avd list command failed" << output << config.sdkToolsVersion();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
avdList = parseAvdList(output);
|
|
||||||
} while (output.contains(avdManufacturerError));
|
|
||||||
|
|
||||||
for (const QString &avdPathStr : qAsConst(avdErrorPaths))
|
|
||||||
AvdConfigEditManufacturerTag(avdPathStr, true);
|
|
||||||
|
|
||||||
return avdList;
|
|
||||||
}
|
|
||||||
|
|
||||||
AndroidDeviceInfoList AvdManagerOutputParser::parseAvdList(const QString &output)
|
|
||||||
{
|
|
||||||
AndroidDeviceInfoList avdList;
|
|
||||||
QStringList avdInfo;
|
|
||||||
auto parseAvdInfo = [&avdInfo, &avdList, this] () {
|
|
||||||
AndroidDeviceInfo avd;
|
|
||||||
if (!avdInfo.filter(avdManufacturerError).isEmpty()) {
|
|
||||||
for (const QString &line : avdInfo) {
|
|
||||||
QString value;
|
|
||||||
if (valueForKey(avdInfoPathKey, line, &value)) {
|
|
||||||
avdErrorPaths.append(value);
|
|
||||||
AvdConfigEditManufacturerTag(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (parseAvd(avdInfo, &avd)) {
|
|
||||||
// armeabi-v7a devices can also run armeabi code
|
|
||||||
if (avd.cpuAbi.contains(ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A))
|
|
||||||
avd.cpuAbi << ProjectExplorer::Constants::ANDROID_ABI_ARMEABI;
|
|
||||||
avd.state = AndroidDeviceInfo::OkState;
|
|
||||||
avd.type = AndroidDeviceInfo::Emulator;
|
|
||||||
avdList << avd;
|
|
||||||
} else {
|
|
||||||
qCDebug(avdManagerLog) << "Avd Parsing: Parsing failed: " << avdInfo;
|
|
||||||
}
|
|
||||||
avdInfo.clear();
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const QString &line : output.split('\n')) {
|
|
||||||
if (line.startsWith("---------") || line.isEmpty())
|
|
||||||
parseAvdInfo();
|
|
||||||
else
|
|
||||||
avdInfo << line;
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils::sort(avdList);
|
|
||||||
|
|
||||||
return avdList;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AvdManagerOutputParser::parseAvd(const QStringList &deviceInfo, AndroidDeviceInfo *avd)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(avd, return false);
|
|
||||||
for (const QString &line : deviceInfo) {
|
|
||||||
QString value;
|
|
||||||
if (valueForKey(avdInfoErrorKey, line)) {
|
|
||||||
qCDebug(avdManagerLog) << "Avd Parsing: Skip avd device. Error key found:" << line;
|
|
||||||
return false;
|
|
||||||
} else if (valueForKey(avdInfoNameKey, line, &value)) {
|
|
||||||
avd->avdname = value;
|
|
||||||
} else if (valueForKey(avdInfoPathKey, line, &value)) {
|
|
||||||
const Utils::FilePath avdPath = Utils::FilePath::fromString(value);
|
|
||||||
if (avdPath.exists())
|
|
||||||
{
|
|
||||||
// Get ABI.
|
|
||||||
const Utils::FilePath configFile = avdPath.pathAppended("config.ini");
|
|
||||||
QSettings config(configFile.toString(), QSettings::IniFormat);
|
|
||||||
value = config.value(avdInfoAbiKey).toString();
|
|
||||||
if (!value.isEmpty())
|
|
||||||
avd->cpuAbi << value;
|
|
||||||
else
|
|
||||||
qCDebug(avdManagerLog) << "Avd Parsing: Cannot find ABI:" << configFile;
|
|
||||||
|
|
||||||
// Get Target
|
|
||||||
const QString avdInfoFileName = avd->avdname + ".ini";
|
|
||||||
const Utils::FilePath
|
|
||||||
avdInfoFile = avdPath.parentDir().pathAppended(avdInfoFileName);
|
|
||||||
QSettings avdInfo(avdInfoFile.toString(), QSettings::IniFormat);
|
|
||||||
value = avdInfo.value(avdInfoTargetKey).toString();
|
|
||||||
if (!value.isEmpty())
|
|
||||||
avd->sdk = value.section('-', -1).toInt();
|
|
||||||
else
|
|
||||||
qCDebug(avdManagerLog) << "Avd Parsing: Cannot find sdk API:" << avdInfoFile.toString();
|
|
||||||
}
|
|
||||||
} else if (valueForKey(avdInfoDeviceKey, line, &value)) {
|
|
||||||
avd->avdDevice = value.remove(0, 2);
|
|
||||||
} else if (valueForKey(avdInfoTargetTypeKey, line, &value)) {
|
|
||||||
avd->avdTarget = value.remove(0, 2);
|
|
||||||
} else if (valueForKey(avdInfoSkinKey, line, &value)) {
|
|
||||||
avd->avdSkin = value.remove(0, 2);
|
|
||||||
} else if (valueForKey(avdInfoSdcardKey, line, &value)) {
|
|
||||||
avd->avdSdcardSize = value.remove(0, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Android
|
} // namespace Android
|
||||||
|
@@ -32,8 +32,6 @@
|
|||||||
namespace Android {
|
namespace Android {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class AvdManagerOutputParser;
|
|
||||||
|
|
||||||
class AndroidAvdManager
|
class AndroidAvdManager
|
||||||
{
|
{
|
||||||
Q_DECLARE_TR_FUNCTIONS(Android::Internal::AndroidAvdManager)
|
Q_DECLARE_TR_FUNCTIONS(Android::Internal::AndroidAvdManager)
|
||||||
@@ -62,7 +60,6 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const AndroidConfig &m_config;
|
const AndroidConfig &m_config;
|
||||||
std::unique_ptr<AvdManagerOutputParser> m_parser;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -1388,31 +1388,6 @@ Environment AndroidConfigurations::toolsEnvironment(const AndroidConfig &config)
|
|||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Workaround for '????????????' serial numbers
|
|
||||||
* @return ("-d") for buggy devices, ("-s", <serial no>) for normal
|
|
||||||
*/
|
|
||||||
QStringList AndroidDeviceInfo::adbSelector(const QString &serialNumber)
|
|
||||||
{
|
|
||||||
if (serialNumber.startsWith(QLatin1String("????")))
|
|
||||||
return QStringList("-d");
|
|
||||||
return QStringList({"-s", serialNumber});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AndroidDeviceInfo::operator<(const AndroidDeviceInfo &other) const
|
|
||||||
{
|
|
||||||
if (serialNumber.contains("????") != other.serialNumber.contains("????"))
|
|
||||||
return !serialNumber.contains("????");
|
|
||||||
if (type != other.type)
|
|
||||||
return type == AndroidDeviceInfo::Hardware;
|
|
||||||
if (sdk != other.sdk)
|
|
||||||
return sdk < other.sdk;
|
|
||||||
if (avdname != other.avdname)
|
|
||||||
return avdname < other.avdname;
|
|
||||||
|
|
||||||
return serialNumber < other.serialNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AndroidConfig &AndroidConfigurations::currentConfig()
|
const AndroidConfig &AndroidConfigurations::currentConfig()
|
||||||
{
|
{
|
||||||
return m_instance->m_config; // ensure that m_instance is initialized
|
return m_instance->m_config; // ensure that m_instance is initialized
|
||||||
@@ -1561,13 +1536,4 @@ void AndroidConfigurations::updateAndroidDevice()
|
|||||||
|
|
||||||
AndroidConfigurations *AndroidConfigurations::m_instance = nullptr;
|
AndroidConfigurations *AndroidConfigurations::m_instance = nullptr;
|
||||||
|
|
||||||
QDebug &operator<<(QDebug &stream, const AndroidDeviceInfo &device)
|
|
||||||
{
|
|
||||||
stream << "Type:"<< (device.type == AndroidDeviceInfo::Emulator ? "Emulator" : "Device")
|
|
||||||
<< ", ABI:" << device.cpuAbi << ", Serial:" << device.serialNumber
|
|
||||||
<< ", Name:" << device.avdname << ", API:" << device.sdk
|
|
||||||
<< ", Authorised:" << !device.unauthorized;
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Android
|
} // namespace Android
|
||||||
|
@@ -26,8 +26,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "android_global.h"
|
#include "android_global.h"
|
||||||
#include "androidsdkpackage.h"
|
#include "androiddeviceinfo.h"
|
||||||
#include "androidsdkmanager.h"
|
#include "androidsdkmanager.h"
|
||||||
|
#include "androidsdkpackage.h"
|
||||||
|
|
||||||
#include <projectexplorer/toolchain.h>
|
#include <projectexplorer/toolchain.h>
|
||||||
#include <qtsupport/qtversionmanager.h>
|
#include <qtsupport/qtversionmanager.h>
|
||||||
@@ -58,31 +59,6 @@ class AndroidSdkManager;
|
|||||||
class AndroidPluginPrivate;
|
class AndroidPluginPrivate;
|
||||||
}
|
}
|
||||||
|
|
||||||
class AndroidDeviceInfo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QString serialNumber;
|
|
||||||
QString avdname;
|
|
||||||
QStringList cpuAbi;
|
|
||||||
QString avdTarget;
|
|
||||||
QString avdDevice;
|
|
||||||
QString avdSkin;
|
|
||||||
QString avdSdcardSize;
|
|
||||||
|
|
||||||
int sdk = -1;
|
|
||||||
enum State { OkState, UnAuthorizedState, OfflineState };
|
|
||||||
State state = OfflineState;
|
|
||||||
bool unauthorized = false;
|
|
||||||
enum AndroidDeviceType { Hardware, Emulator };
|
|
||||||
AndroidDeviceType type = Emulator;
|
|
||||||
|
|
||||||
static QStringList adbSelector(const QString &serialNumber);
|
|
||||||
|
|
||||||
bool isValid() const { return !serialNumber.isEmpty() || !avdname.isEmpty(); }
|
|
||||||
bool operator<(const AndroidDeviceInfo &other) const;
|
|
||||||
};
|
|
||||||
using AndroidDeviceInfoList = QList<AndroidDeviceInfo>;
|
|
||||||
|
|
||||||
class CreateAvdInfo
|
class CreateAvdInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -269,8 +245,4 @@ private:
|
|||||||
bool m_force32bit;
|
bool m_force32bit;
|
||||||
};
|
};
|
||||||
|
|
||||||
QDebug &operator<<(QDebug &stream, const AndroidDeviceInfo &device);
|
|
||||||
|
|
||||||
} // namespace Android
|
} // namespace Android
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(Android::AndroidDeviceInfo)
|
|
||||||
|
72
src/plugins/android/androiddeviceinfo.cpp
Normal file
72
src/plugins/android/androiddeviceinfo.cpp
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** 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
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "androiddeviceinfo.h"
|
||||||
|
|
||||||
|
namespace Android {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Workaround for '????????????' serial numbers
|
||||||
|
* @return ("-d") for buggy devices, ("-s", <serial no>) for normal
|
||||||
|
*/
|
||||||
|
QStringList AndroidDeviceInfo::adbSelector(const QString &serialNumber)
|
||||||
|
{
|
||||||
|
if (serialNumber.startsWith(QLatin1String("????")))
|
||||||
|
return QStringList("-d");
|
||||||
|
return QStringList({"-s", serialNumber});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AndroidDeviceInfo::operator<(const AndroidDeviceInfo &other) const
|
||||||
|
{
|
||||||
|
if (serialNumber.contains("????") != other.serialNumber.contains("????"))
|
||||||
|
return !serialNumber.contains("????");
|
||||||
|
if (type != other.type)
|
||||||
|
return type == AndroidDeviceInfo::Hardware;
|
||||||
|
if (sdk != other.sdk)
|
||||||
|
return sdk < other.sdk;
|
||||||
|
if (avdname != other.avdname)
|
||||||
|
return avdname < other.avdname;
|
||||||
|
|
||||||
|
return serialNumber < other.serialNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AndroidDeviceInfo::operator==(const AndroidDeviceInfo &other) const
|
||||||
|
{
|
||||||
|
return serialNumber == other.serialNumber && avdname == other.avdname && cpuAbi == other.cpuAbi
|
||||||
|
&& avdTarget == other.avdTarget && avdDevice == other.avdDevice
|
||||||
|
&& avdSkin == other.avdSkin && avdSdcardSize == other.avdSdcardSize && sdk == other.sdk
|
||||||
|
&& state == other.state && unauthorized == other.unauthorized && type == other.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug &operator<<(QDebug &stream, const AndroidDeviceInfo &device)
|
||||||
|
{
|
||||||
|
stream << "Type:" << (device.type == AndroidDeviceInfo::Emulator ? "Emulator" : "Device")
|
||||||
|
<< ", ABI:" << device.cpuAbi << ", Serial:" << device.serialNumber
|
||||||
|
<< ", Name:" << device.avdname << ", API:" << device.sdk
|
||||||
|
<< ", Authorised:" << !device.unauthorized;
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Android
|
65
src/plugins/android/androiddeviceinfo.h
Normal file
65
src/plugins/android/androiddeviceinfo.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** 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
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QMetaType>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
namespace Android {
|
||||||
|
|
||||||
|
class AndroidDeviceInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString serialNumber;
|
||||||
|
QString avdname;
|
||||||
|
QStringList cpuAbi;
|
||||||
|
QString avdTarget;
|
||||||
|
QString avdDevice;
|
||||||
|
QString avdSkin;
|
||||||
|
QString avdSdcardSize;
|
||||||
|
|
||||||
|
int sdk = -1;
|
||||||
|
enum State { OkState, UnAuthorizedState, OfflineState };
|
||||||
|
State state = OfflineState;
|
||||||
|
bool unauthorized = false;
|
||||||
|
enum AndroidDeviceType { Hardware, Emulator };
|
||||||
|
AndroidDeviceType type = Emulator;
|
||||||
|
|
||||||
|
static QStringList adbSelector(const QString &serialNumber);
|
||||||
|
|
||||||
|
bool isValid() const { return !serialNumber.isEmpty() || !avdname.isEmpty(); }
|
||||||
|
bool operator<(const AndroidDeviceInfo &other) const;
|
||||||
|
bool operator==(const AndroidDeviceInfo &other) const; // should be = default with C++20
|
||||||
|
};
|
||||||
|
using AndroidDeviceInfoList = QList<AndroidDeviceInfo>;
|
||||||
|
|
||||||
|
QDebug &operator<<(QDebug &stream, const AndroidDeviceInfo &device);
|
||||||
|
|
||||||
|
} // namespace Android
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Android::AndroidDeviceInfo)
|
164
src/plugins/android/avdmanageroutputparser.cpp
Normal file
164
src/plugins/android/avdmanageroutputparser.cpp
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** 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
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "avdmanageroutputparser.h"
|
||||||
|
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/variant.h>
|
||||||
|
|
||||||
|
#include <QLoggingCategory>
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
Q_LOGGING_CATEGORY(avdOutputParserLog, "qtc.android.avdOutputParser", QtWarningMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avd list keys to parse avd
|
||||||
|
const char avdInfoNameKey[] = "Name:";
|
||||||
|
const char avdInfoPathKey[] = "Path:";
|
||||||
|
const char avdInfoAbiKey[] = "abi.type";
|
||||||
|
const char avdInfoTargetKey[] = "target";
|
||||||
|
const char avdInfoErrorKey[] = "Error:";
|
||||||
|
const char avdInfoSdcardKey[] = "Sdcard";
|
||||||
|
const char avdInfoTargetTypeKey[] = "Target";
|
||||||
|
const char avdInfoDeviceKey[] = "Device";
|
||||||
|
const char avdInfoSkinKey[] = "Skin";
|
||||||
|
|
||||||
|
namespace Android {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Parses the \a line for a [spaces]key[spaces]value[spaces] pattern and returns
|
||||||
|
\c true if the key is found, \c false otherwise. The value is copied into \a value.
|
||||||
|
*/
|
||||||
|
static bool valueForKey(QString key, const QString &line, QString *value = nullptr)
|
||||||
|
{
|
||||||
|
auto trimmedInput = line.trimmed();
|
||||||
|
if (trimmedInput.startsWith(key)) {
|
||||||
|
if (value)
|
||||||
|
*value = trimmedInput.section(key, 1, 1).trimmed();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool parseAvd(const QStringList &deviceInfo, AndroidDeviceInfo *avd)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(avd, return false);
|
||||||
|
for (const QString &line : deviceInfo) {
|
||||||
|
QString value;
|
||||||
|
if (valueForKey(avdInfoErrorKey, line)) {
|
||||||
|
qCDebug(avdOutputParserLog) << "Avd Parsing: Skip avd device. Error key found:" << line;
|
||||||
|
return false;
|
||||||
|
} else if (valueForKey(avdInfoNameKey, line, &value)) {
|
||||||
|
avd->avdname = value;
|
||||||
|
} else if (valueForKey(avdInfoPathKey, line, &value)) {
|
||||||
|
const Utils::FilePath avdPath = Utils::FilePath::fromString(value);
|
||||||
|
if (avdPath.exists()) {
|
||||||
|
// Get ABI.
|
||||||
|
const Utils::FilePath configFile = avdPath.pathAppended("config.ini");
|
||||||
|
QSettings config(configFile.toString(), QSettings::IniFormat);
|
||||||
|
value = config.value(avdInfoAbiKey).toString();
|
||||||
|
if (!value.isEmpty())
|
||||||
|
avd->cpuAbi << value;
|
||||||
|
else
|
||||||
|
qCDebug(avdOutputParserLog) << "Avd Parsing: Cannot find ABI:" << configFile;
|
||||||
|
|
||||||
|
// Get Target
|
||||||
|
const QString avdInfoFileName = avd->avdname + ".ini";
|
||||||
|
const Utils::FilePath avdInfoFile = avdPath.parentDir().pathAppended(
|
||||||
|
avdInfoFileName);
|
||||||
|
QSettings avdInfo(avdInfoFile.toString(), QSettings::IniFormat);
|
||||||
|
value = avdInfo.value(avdInfoTargetKey).toString();
|
||||||
|
if (!value.isEmpty())
|
||||||
|
avd->sdk = value.section('-', -1).toInt();
|
||||||
|
else
|
||||||
|
qCDebug(avdOutputParserLog)
|
||||||
|
<< "Avd Parsing: Cannot find sdk API:" << avdInfoFile.toString();
|
||||||
|
}
|
||||||
|
} else if (valueForKey(avdInfoDeviceKey, line, &value)) {
|
||||||
|
avd->avdDevice = value.remove(0, 2);
|
||||||
|
} else if (valueForKey(avdInfoTargetTypeKey, line, &value)) {
|
||||||
|
avd->avdTarget = value.remove(0, 2);
|
||||||
|
} else if (valueForKey(avdInfoSkinKey, line, &value)) {
|
||||||
|
avd->avdSkin = value.remove(0, 2);
|
||||||
|
} else if (valueForKey(avdInfoSdcardKey, line, &value)) {
|
||||||
|
avd->avdSdcardSize = value.remove(0, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidDeviceInfoList parseAvdList(const QString &output, QStringList *avdErrorPaths)
|
||||||
|
{
|
||||||
|
QTC_CHECK(avdErrorPaths);
|
||||||
|
AndroidDeviceInfoList avdList;
|
||||||
|
QStringList avdInfo;
|
||||||
|
using ErrorPath = QString;
|
||||||
|
using AvdResult = Utils::variant<std::monostate, AndroidDeviceInfo, ErrorPath>;
|
||||||
|
const auto parseAvdInfo = [](const QStringList &avdInfo) {
|
||||||
|
AndroidDeviceInfo avd;
|
||||||
|
if (!avdInfo.filter(avdManufacturerError).isEmpty()) {
|
||||||
|
for (const QString &line : avdInfo) {
|
||||||
|
QString value;
|
||||||
|
if (valueForKey(avdInfoPathKey, line, &value))
|
||||||
|
return AvdResult(value); // error path
|
||||||
|
}
|
||||||
|
} else if (parseAvd(avdInfo, &avd)) {
|
||||||
|
// armeabi-v7a devices can also run armeabi code
|
||||||
|
if (avd.cpuAbi.contains(ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A))
|
||||||
|
avd.cpuAbi << ProjectExplorer::Constants::ANDROID_ABI_ARMEABI;
|
||||||
|
avd.state = AndroidDeviceInfo::OkState;
|
||||||
|
avd.type = AndroidDeviceInfo::Emulator;
|
||||||
|
return AvdResult(avd);
|
||||||
|
} else {
|
||||||
|
qCDebug(avdOutputParserLog) << "Avd Parsing: Parsing failed: " << avdInfo;
|
||||||
|
}
|
||||||
|
return AvdResult();
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const QString &line : output.split('\n')) {
|
||||||
|
if (line.startsWith("---------") || line.isEmpty()) {
|
||||||
|
const AvdResult result = parseAvdInfo(avdInfo);
|
||||||
|
if (auto info = Utils::get_if<AndroidDeviceInfo>(&result))
|
||||||
|
avdList << *info;
|
||||||
|
else if (auto errorPath = Utils::get_if<ErrorPath>(&result))
|
||||||
|
*avdErrorPaths << *errorPath;
|
||||||
|
avdInfo.clear();
|
||||||
|
} else {
|
||||||
|
avdInfo << line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::sort(avdList);
|
||||||
|
|
||||||
|
return avdList;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Android
|
36
src/plugins/android/avdmanageroutputparser.h
Normal file
36
src/plugins/android/avdmanageroutputparser.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** 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
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "androiddeviceinfo.h"
|
||||||
|
|
||||||
|
namespace Android {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
const char avdManufacturerError[] = "no longer exists as a device";
|
||||||
|
|
||||||
|
AndroidDeviceInfoList parseAvdList(const QString &output, QStringList *avdErrorPaths);
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Android
|
@@ -1,5 +1,6 @@
|
|||||||
add_subdirectory(aggregation)
|
add_subdirectory(aggregation)
|
||||||
add_subdirectory(algorithm)
|
add_subdirectory(algorithm)
|
||||||
|
add_subdirectory(android)
|
||||||
add_subdirectory(changeset)
|
add_subdirectory(changeset)
|
||||||
add_subdirectory(cplusplus)
|
add_subdirectory(cplusplus)
|
||||||
add_subdirectory(debugger)
|
add_subdirectory(debugger)
|
||||||
|
18
tests/auto/android/CMakeLists.txt
Normal file
18
tests/auto/android/CMakeLists.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
add_qtc_test(tst_avdmanageroutputparser
|
||||||
|
DEPENDS Utils
|
||||||
|
INCLUDES
|
||||||
|
"${PROJECT_SOURCE_DIR}/src/plugins"
|
||||||
|
"${PROJECT_SOURCE_DIR}/src/plugins/android"
|
||||||
|
SOURCES
|
||||||
|
tst_avdmanageroutputparser.cpp
|
||||||
|
"${PROJECT_SOURCE_DIR}/src/plugins/android/avdmanageroutputparser.cpp"
|
||||||
|
"${PROJECT_SOURCE_DIR}/src/plugins/android/avdmanageroutputparser.h"
|
||||||
|
"${PROJECT_SOURCE_DIR}/src/plugins/android/androiddeviceinfo.cpp"
|
||||||
|
"${PROJECT_SOURCE_DIR}/src/plugins/android/androiddeviceinfo.h"
|
||||||
|
)
|
||||||
|
|
||||||
|
qtc_add_resources(tst_avdmanageroutputparser tst_avdmanageroutputparser_rcc
|
||||||
|
FILES
|
||||||
|
Test.avd/config.ini
|
||||||
|
TestTablet.avd/config.ini
|
||||||
|
)
|
119
tests/auto/android/Test.avd/config.ini
Normal file
119
tests/auto/android/Test.avd/config.ini
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
PlayStore.enabled=no
|
||||||
|
abi.type=x86
|
||||||
|
avd.id=<build>
|
||||||
|
avd.ini.encoding=UTF-8
|
||||||
|
avd.name=<build>
|
||||||
|
disk.cachePartition=yes
|
||||||
|
disk.cachePartition.size=66MB
|
||||||
|
disk.dataPartition.path=<temp>
|
||||||
|
disk.dataPartition.size=800M
|
||||||
|
disk.systemPartition.size=0
|
||||||
|
disk.vendorPartition.size=0
|
||||||
|
fastboot.forceChosenSnapshotBoot=no
|
||||||
|
fastboot.forceColdBoot=no
|
||||||
|
fastboot.forceFastBoot=yes
|
||||||
|
hw.accelerometer=yes
|
||||||
|
hw.arc=no
|
||||||
|
hw.arc.autologin=no
|
||||||
|
hw.audioInput=yes
|
||||||
|
hw.audioOutput=yes
|
||||||
|
hw.battery=yes
|
||||||
|
hw.camera.back=emulated
|
||||||
|
hw.camera.front=none
|
||||||
|
hw.cpu.arch=x86
|
||||||
|
hw.cpu.ncore=4
|
||||||
|
hw.dPad=no
|
||||||
|
hw.device.hash2=MD5:5c288d27461585ecc73a535555e7cf61
|
||||||
|
hw.device.manufacturer=Google
|
||||||
|
hw.device.name=Galaxy Nexus
|
||||||
|
hw.display1.density=0
|
||||||
|
hw.display1.flag=0
|
||||||
|
hw.display1.height=0
|
||||||
|
hw.display1.width=0
|
||||||
|
hw.display1.xOffset=-1
|
||||||
|
hw.display1.yOffset=-1
|
||||||
|
hw.display2.density=0
|
||||||
|
hw.display2.flag=0
|
||||||
|
hw.display2.height=0
|
||||||
|
hw.display2.width=0
|
||||||
|
hw.display2.xOffset=-1
|
||||||
|
hw.display2.yOffset=-1
|
||||||
|
hw.display3.density=0
|
||||||
|
hw.display3.flag=0
|
||||||
|
hw.display3.height=0
|
||||||
|
hw.display3.width=0
|
||||||
|
hw.display3.xOffset=-1
|
||||||
|
hw.display3.yOffset=-1
|
||||||
|
hw.displayRegion.0.1.height=0
|
||||||
|
hw.displayRegion.0.1.width=0
|
||||||
|
hw.displayRegion.0.1.xOffset=-1
|
||||||
|
hw.displayRegion.0.1.yOffset=-1
|
||||||
|
hw.displayRegion.0.2.height=0
|
||||||
|
hw.displayRegion.0.2.width=0
|
||||||
|
hw.displayRegion.0.2.xOffset=-1
|
||||||
|
hw.displayRegion.0.2.yOffset=-1
|
||||||
|
hw.displayRegion.0.3.height=0
|
||||||
|
hw.displayRegion.0.3.width=0
|
||||||
|
hw.displayRegion.0.3.xOffset=-1
|
||||||
|
hw.displayRegion.0.3.yOffset=-1
|
||||||
|
hw.gltransport=pipe
|
||||||
|
hw.gltransport.asg.dataRingSize=32768
|
||||||
|
hw.gltransport.asg.writeBufferSize=1048576
|
||||||
|
hw.gltransport.asg.writeStepSize=4096
|
||||||
|
hw.gltransport.drawFlushInterval=800
|
||||||
|
hw.gps=yes
|
||||||
|
hw.gpu.enabled=no
|
||||||
|
hw.gpu.mode=auto
|
||||||
|
hw.gsmModem=yes
|
||||||
|
hw.gyroscope=yes
|
||||||
|
hw.initialOrientation=portrait
|
||||||
|
hw.keyboard=no
|
||||||
|
hw.keyboard.charmap=qwerty2
|
||||||
|
hw.keyboard.lid=yes
|
||||||
|
hw.lcd.backlight=yes
|
||||||
|
hw.lcd.density=320
|
||||||
|
hw.lcd.depth=16
|
||||||
|
hw.lcd.height=1280
|
||||||
|
hw.lcd.vsync=60
|
||||||
|
hw.lcd.width=720
|
||||||
|
hw.mainKeys=no
|
||||||
|
hw.ramSize=1024
|
||||||
|
hw.rotaryInput=no
|
||||||
|
hw.screen=multi-touch
|
||||||
|
hw.sdCard=no
|
||||||
|
hw.sensor.hinge=yes
|
||||||
|
hw.sensor.hinge.count=0
|
||||||
|
hw.sensor.hinge.fold_to_displayRegion.0.1_at_posture=1
|
||||||
|
hw.sensor.hinge.sub_type=0
|
||||||
|
hw.sensor.hinge.type=0
|
||||||
|
hw.sensor.roll=no
|
||||||
|
hw.sensor.roll.count=0
|
||||||
|
hw.sensor.roll.resize_to_displayRegion.0.1_at_posture=6
|
||||||
|
hw.sensor.roll.resize_to_displayRegion.0.2_at_posture=6
|
||||||
|
hw.sensor.roll.resize_to_displayRegion.0.3_at_posture=6
|
||||||
|
hw.sensors.gyroscope_uncalibrated=yes
|
||||||
|
hw.sensors.heart_rate=no
|
||||||
|
hw.sensors.humidity=yes
|
||||||
|
hw.sensors.light=yes
|
||||||
|
hw.sensors.magnetic_field=yes
|
||||||
|
hw.sensors.magnetic_field_uncalibrated=yes
|
||||||
|
hw.sensors.orientation=yes
|
||||||
|
hw.sensors.pressure=yes
|
||||||
|
hw.sensors.proximity=yes
|
||||||
|
hw.sensors.temperature=yes
|
||||||
|
hw.trackBall=no
|
||||||
|
hw.useext4=yes
|
||||||
|
image.sysdir.1=system-images/android-30/google_apis/x86/
|
||||||
|
kernel.newDeviceNaming=autodetect
|
||||||
|
kernel.supportsYaffs2=autodetect
|
||||||
|
runtime.network.latency=None
|
||||||
|
runtime.network.speed=Full
|
||||||
|
sdcard.size=512 MB
|
||||||
|
showDeviceFrame=yes
|
||||||
|
skin.path=_no_skin
|
||||||
|
tag.display=Google APIs
|
||||||
|
tag.id=google_apis
|
||||||
|
test.delayAdbTillBootComplete=0
|
||||||
|
test.monitorAdb=0
|
||||||
|
test.quitAfterBootTimeOut=-1
|
||||||
|
vm.heapSize=112M
|
119
tests/auto/android/TestTablet.avd/config.ini
Normal file
119
tests/auto/android/TestTablet.avd/config.ini
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
PlayStore.enabled=no
|
||||||
|
abi.type=x86
|
||||||
|
avd.id=<build>
|
||||||
|
avd.ini.encoding=UTF-8
|
||||||
|
avd.name=<build>
|
||||||
|
disk.cachePartition=yes
|
||||||
|
disk.cachePartition.size=66MB
|
||||||
|
disk.dataPartition.path=<temp>
|
||||||
|
disk.dataPartition.size=800M
|
||||||
|
disk.systemPartition.size=0
|
||||||
|
disk.vendorPartition.size=0
|
||||||
|
fastboot.forceChosenSnapshotBoot=no
|
||||||
|
fastboot.forceColdBoot=no
|
||||||
|
fastboot.forceFastBoot=yes
|
||||||
|
hw.accelerometer=yes
|
||||||
|
hw.arc=no
|
||||||
|
hw.arc.autologin=no
|
||||||
|
hw.audioInput=yes
|
||||||
|
hw.audioOutput=yes
|
||||||
|
hw.battery=yes
|
||||||
|
hw.camera.back=emulated
|
||||||
|
hw.camera.front=none
|
||||||
|
hw.cpu.arch=x86
|
||||||
|
hw.cpu.ncore=4
|
||||||
|
hw.dPad=no
|
||||||
|
hw.device.hash2=MD5:6f5876a1c548aef127b373f80cac4953
|
||||||
|
hw.device.manufacturer=Generic
|
||||||
|
hw.device.name=7in WSVGA (Tablet)
|
||||||
|
hw.display1.density=0
|
||||||
|
hw.display1.flag=0
|
||||||
|
hw.display1.height=0
|
||||||
|
hw.display1.width=0
|
||||||
|
hw.display1.xOffset=-1
|
||||||
|
hw.display1.yOffset=-1
|
||||||
|
hw.display2.density=0
|
||||||
|
hw.display2.flag=0
|
||||||
|
hw.display2.height=0
|
||||||
|
hw.display2.width=0
|
||||||
|
hw.display2.xOffset=-1
|
||||||
|
hw.display2.yOffset=-1
|
||||||
|
hw.display3.density=0
|
||||||
|
hw.display3.flag=0
|
||||||
|
hw.display3.height=0
|
||||||
|
hw.display3.width=0
|
||||||
|
hw.display3.xOffset=-1
|
||||||
|
hw.display3.yOffset=-1
|
||||||
|
hw.displayRegion.0.1.height=0
|
||||||
|
hw.displayRegion.0.1.width=0
|
||||||
|
hw.displayRegion.0.1.xOffset=-1
|
||||||
|
hw.displayRegion.0.1.yOffset=-1
|
||||||
|
hw.displayRegion.0.2.height=0
|
||||||
|
hw.displayRegion.0.2.width=0
|
||||||
|
hw.displayRegion.0.2.xOffset=-1
|
||||||
|
hw.displayRegion.0.2.yOffset=-1
|
||||||
|
hw.displayRegion.0.3.height=0
|
||||||
|
hw.displayRegion.0.3.width=0
|
||||||
|
hw.displayRegion.0.3.xOffset=-1
|
||||||
|
hw.displayRegion.0.3.yOffset=-1
|
||||||
|
hw.gltransport=pipe
|
||||||
|
hw.gltransport.asg.dataRingSize=32768
|
||||||
|
hw.gltransport.asg.writeBufferSize=1048576
|
||||||
|
hw.gltransport.asg.writeStepSize=4096
|
||||||
|
hw.gltransport.drawFlushInterval=800
|
||||||
|
hw.gps=yes
|
||||||
|
hw.gpu.enabled=no
|
||||||
|
hw.gpu.mode=auto
|
||||||
|
hw.gsmModem=yes
|
||||||
|
hw.gyroscope=yes
|
||||||
|
hw.initialOrientation=portrait
|
||||||
|
hw.keyboard=no
|
||||||
|
hw.keyboard.charmap=qwerty2
|
||||||
|
hw.keyboard.lid=yes
|
||||||
|
hw.lcd.backlight=yes
|
||||||
|
hw.lcd.density=160
|
||||||
|
hw.lcd.depth=16
|
||||||
|
hw.lcd.height=600
|
||||||
|
hw.lcd.vsync=60
|
||||||
|
hw.lcd.width=1024
|
||||||
|
hw.mainKeys=no
|
||||||
|
hw.ramSize=512
|
||||||
|
hw.rotaryInput=no
|
||||||
|
hw.screen=multi-touch
|
||||||
|
hw.sdCard=no
|
||||||
|
hw.sensor.hinge=yes
|
||||||
|
hw.sensor.hinge.count=0
|
||||||
|
hw.sensor.hinge.fold_to_displayRegion.0.1_at_posture=1
|
||||||
|
hw.sensor.hinge.sub_type=0
|
||||||
|
hw.sensor.hinge.type=0
|
||||||
|
hw.sensor.roll=no
|
||||||
|
hw.sensor.roll.count=0
|
||||||
|
hw.sensor.roll.resize_to_displayRegion.0.1_at_posture=6
|
||||||
|
hw.sensor.roll.resize_to_displayRegion.0.2_at_posture=6
|
||||||
|
hw.sensor.roll.resize_to_displayRegion.0.3_at_posture=6
|
||||||
|
hw.sensors.gyroscope_uncalibrated=yes
|
||||||
|
hw.sensors.heart_rate=no
|
||||||
|
hw.sensors.humidity=yes
|
||||||
|
hw.sensors.light=yes
|
||||||
|
hw.sensors.magnetic_field=yes
|
||||||
|
hw.sensors.magnetic_field_uncalibrated=yes
|
||||||
|
hw.sensors.orientation=yes
|
||||||
|
hw.sensors.pressure=yes
|
||||||
|
hw.sensors.proximity=yes
|
||||||
|
hw.sensors.temperature=yes
|
||||||
|
hw.trackBall=no
|
||||||
|
hw.useext4=yes
|
||||||
|
image.sysdir.1=system-images/android-30/google_apis/x86/
|
||||||
|
kernel.newDeviceNaming=autodetect
|
||||||
|
kernel.supportsYaffs2=autodetect
|
||||||
|
runtime.network.latency=None
|
||||||
|
runtime.network.speed=Full
|
||||||
|
sdcard.size=512 MB
|
||||||
|
showDeviceFrame=yes
|
||||||
|
skin.path=_no_skin
|
||||||
|
tag.display=Google APIs
|
||||||
|
tag.id=google_apis
|
||||||
|
test.delayAdbTillBootComplete=0
|
||||||
|
test.monitorAdb=0
|
||||||
|
test.quitAfterBootTimeOut=-1
|
||||||
|
vm.heapSize=112M
|
121
tests/auto/android/tst_avdmanageroutputparser.cpp
Normal file
121
tests/auto/android/tst_avdmanageroutputparser.cpp
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** 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
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "avdmanageroutputparser.h"
|
||||||
|
|
||||||
|
#include <QtTest>
|
||||||
|
|
||||||
|
using namespace Android;
|
||||||
|
using namespace Android::Internal;
|
||||||
|
|
||||||
|
class tst_AvdManagerOutputParser : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void parse_data();
|
||||||
|
void parse();
|
||||||
|
};
|
||||||
|
|
||||||
|
void tst_AvdManagerOutputParser::parse_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("input");
|
||||||
|
QTest::addColumn<AndroidDeviceInfoList>("output");
|
||||||
|
QTest::addColumn<QStringList>("errorPaths");
|
||||||
|
|
||||||
|
QTest::newRow("one") << "Available Android Virtual Devices:\n"
|
||||||
|
" Name: Test\n"
|
||||||
|
" Device: Galaxy Nexus (Google)\n"
|
||||||
|
" Path: :Test.avd\n"
|
||||||
|
" Target: Google APIs (Google Inc.)\n"
|
||||||
|
" Based on: Android API 30 Tag/ABI: google_apis/x86\n"
|
||||||
|
" Sdcard: 512 MB\n"
|
||||||
|
<< AndroidDeviceInfoList({{"",
|
||||||
|
"Test",
|
||||||
|
{"x86"},
|
||||||
|
"Google APIs (Google Inc.)",
|
||||||
|
"Galaxy Nexus (Google)",
|
||||||
|
"",
|
||||||
|
"512 MB",
|
||||||
|
-1,
|
||||||
|
AndroidDeviceInfo::OkState,
|
||||||
|
false,
|
||||||
|
AndroidDeviceInfo::Emulator}})
|
||||||
|
<< QStringList();
|
||||||
|
|
||||||
|
QTest::newRow("two") << "Available Android Virtual Devices:\n"
|
||||||
|
" Name: Test\n"
|
||||||
|
" Device: Galaxy Nexus (Google)\n"
|
||||||
|
" Path: :Test.avd\n"
|
||||||
|
" Target: Google APIs (Google Inc.)\n"
|
||||||
|
" Based on: Android API 30 Tag/ABI: google_apis/x86\n"
|
||||||
|
" Sdcard: 512 MB\n"
|
||||||
|
"---------\n"
|
||||||
|
" Name: TestTablet\n"
|
||||||
|
" Device: 7in WSVGA (Tablet) (Generic)\n"
|
||||||
|
" Path: :TestTablet.avd\n"
|
||||||
|
" Target: Google APIs (Google Inc.)\n"
|
||||||
|
" Based on: Android API 30 Tag/ABI: google_apis/x86\n"
|
||||||
|
" Sdcard: 256 MB\n"
|
||||||
|
<< AndroidDeviceInfoList({{"",
|
||||||
|
"Test",
|
||||||
|
{"x86"},
|
||||||
|
"Google APIs (Google Inc.)",
|
||||||
|
"Galaxy Nexus (Google)",
|
||||||
|
"",
|
||||||
|
"512 MB",
|
||||||
|
-1,
|
||||||
|
AndroidDeviceInfo::OkState,
|
||||||
|
false,
|
||||||
|
AndroidDeviceInfo::Emulator},
|
||||||
|
{"",
|
||||||
|
"TestTablet",
|
||||||
|
{"x86"},
|
||||||
|
"Google APIs (Google Inc.)",
|
||||||
|
"7in WSVGA (Tablet) (Generic)",
|
||||||
|
"",
|
||||||
|
"256 MB",
|
||||||
|
-1,
|
||||||
|
AndroidDeviceInfo::OkState,
|
||||||
|
false,
|
||||||
|
AndroidDeviceInfo::Emulator}})
|
||||||
|
<< QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_AvdManagerOutputParser::parse()
|
||||||
|
{
|
||||||
|
QFETCH(QString, input);
|
||||||
|
QFETCH(AndroidDeviceInfoList, output);
|
||||||
|
QFETCH(QStringList, errorPaths);
|
||||||
|
|
||||||
|
QStringList avdErrorPaths;
|
||||||
|
const auto result = parseAvdList(input, &avdErrorPaths);
|
||||||
|
QCOMPARE(result, output);
|
||||||
|
QCOMPARE(avdErrorPaths, errorPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_AvdManagerOutputParser)
|
||||||
|
|
||||||
|
#include "tst_avdmanageroutputparser.moc"
|
Reference in New Issue
Block a user