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
|
||||
androiddevice.cpp androiddevice.h
|
||||
androiddevicedialog.cpp androiddevicedialog.h androiddevicedialog.ui
|
||||
androiddeviceinfo.cpp androiddeviceinfo.h
|
||||
androiderrormessage.cpp androiderrormessage.h
|
||||
androidextralibrarylistmodel.cpp androidextralibrarylistmodel.h
|
||||
androidglobal.h
|
||||
@@ -43,6 +44,7 @@ add_qtc_plugin(Android
|
||||
androidsignaloperation.cpp androidsignaloperation.h
|
||||
androidtoolchain.cpp androidtoolchain.h
|
||||
avddialog.cpp avddialog.h
|
||||
avdmanageroutputparser.cpp avdmanageroutputparser.h
|
||||
certificatesmodel.cpp certificatesmodel.h
|
||||
createandroidmanifestwizard.cpp createandroidmanifestwizard.h
|
||||
javaeditor.cpp javaeditor.h
|
||||
|
@@ -27,6 +27,7 @@ HEADERS += \
|
||||
javaparser.h \
|
||||
androidplugin.h \
|
||||
androiddevice.h \
|
||||
androiddeviceinfo.h \
|
||||
androidqmltoolingsupport.h \
|
||||
androidmanifesteditorfactory.h \
|
||||
androidmanifesteditor.h \
|
||||
@@ -40,6 +41,7 @@ HEADERS += \
|
||||
javaeditor.h \
|
||||
javaindenter.h \
|
||||
avddialog.h \
|
||||
avdmanageroutputparser.h \
|
||||
android_global.h \
|
||||
androidbuildapkstep.h \
|
||||
androidsdkmanager.h \
|
||||
@@ -74,6 +76,7 @@ SOURCES += \
|
||||
javaparser.cpp \
|
||||
androidplugin.cpp \
|
||||
androiddevice.cpp \
|
||||
androiddeviceinfo.cpp \
|
||||
androidqmltoolingsupport.cpp \
|
||||
androidmanifesteditorfactory.cpp \
|
||||
androidmanifesteditor.cpp \
|
||||
@@ -87,6 +90,7 @@ SOURCES += \
|
||||
javaeditor.cpp \
|
||||
javaindenter.cpp \
|
||||
avddialog.cpp \
|
||||
avdmanageroutputparser.cpp \
|
||||
androidbuildapkstep.cpp \
|
||||
androidsdkmanager.cpp \
|
||||
androidavdmanager.cpp \
|
||||
|
@@ -40,6 +40,8 @@ Project {
|
||||
"androiddevicedialog.ui",
|
||||
"androiddevice.cpp",
|
||||
"androiddevice.h",
|
||||
"androiddeviceinfo.cpp",
|
||||
"androiddeviceinfo.h",
|
||||
"androiderrormessage.h",
|
||||
"androiderrormessage.cpp",
|
||||
"androidextralibrarylistmodel.cpp",
|
||||
@@ -100,6 +102,8 @@ Project {
|
||||
"androidtoolchain.h",
|
||||
"avddialog.cpp",
|
||||
"avddialog.h",
|
||||
"avdmanageroutputparser.cpp",
|
||||
"avdmanageroutputparser.h",
|
||||
"certificatesmodel.cpp",
|
||||
"certificatesmodel.h",
|
||||
"createandroidmanifestwizard.h",
|
||||
|
@@ -24,6 +24,8 @@
|
||||
****************************************************************************/
|
||||
#include "androidavdmanager.h"
|
||||
|
||||
#include "avdmanageroutputparser.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <utils/algorithm.h>
|
||||
@@ -51,17 +53,6 @@ namespace Internal {
|
||||
|
||||
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;
|
||||
|
||||
/*!
|
||||
@@ -85,21 +76,6 @@ bool AndroidAvdManager::avdManagerCommand(const AndroidConfig &config, const QSt
|
||||
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,
|
||||
int msecs = 3000)
|
||||
{
|
||||
@@ -203,25 +179,8 @@ static void avdProcessFinished(int exitCode, QProcess *p)
|
||||
p->deleteLater();
|
||||
}
|
||||
|
||||
/*!
|
||||
\class AvdManagerOutputParser
|
||||
\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)
|
||||
AndroidAvdManager::AndroidAvdManager(const AndroidConfig &config)
|
||||
: m_config(config)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -243,9 +202,69 @@ bool AndroidAvdManager::removeAvd(const QString &name) const
|
||||
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
|
||||
{
|
||||
return Utils::runAsync(&AvdManagerOutputParser::listVirtualDevices, m_parser.get(), m_config);
|
||||
return Utils::runAsync(listVirtualDevices, m_config);
|
||||
}
|
||||
|
||||
QString AndroidAvdManager::startAvd(const QString &name) const
|
||||
@@ -353,147 +372,7 @@ bool AndroidAvdManager::waitForBooted(const QString &serialNumber,
|
||||
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 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 Android
|
||||
|
@@ -32,8 +32,6 @@
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
class AvdManagerOutputParser;
|
||||
|
||||
class AndroidAvdManager
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Android::Internal::AndroidAvdManager)
|
||||
@@ -62,7 +60,6 @@ private:
|
||||
|
||||
private:
|
||||
const AndroidConfig &m_config;
|
||||
std::unique_ptr<AvdManagerOutputParser> m_parser;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -1388,31 +1388,6 @@ Environment AndroidConfigurations::toolsEnvironment(const AndroidConfig &config)
|
||||
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()
|
||||
{
|
||||
return m_instance->m_config; // ensure that m_instance is initialized
|
||||
@@ -1561,13 +1536,4 @@ void AndroidConfigurations::updateAndroidDevice()
|
||||
|
||||
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
|
||||
|
@@ -26,8 +26,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "android_global.h"
|
||||
#include "androidsdkpackage.h"
|
||||
#include "androiddeviceinfo.h"
|
||||
#include "androidsdkmanager.h"
|
||||
#include "androidsdkpackage.h"
|
||||
|
||||
#include <projectexplorer/toolchain.h>
|
||||
#include <qtsupport/qtversionmanager.h>
|
||||
@@ -58,31 +59,6 @@ class AndroidSdkManager;
|
||||
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
|
||||
{
|
||||
public:
|
||||
@@ -269,8 +245,4 @@ private:
|
||||
bool m_force32bit;
|
||||
};
|
||||
|
||||
QDebug &operator<<(QDebug &stream, const AndroidDeviceInfo &device);
|
||||
|
||||
} // 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(algorithm)
|
||||
add_subdirectory(android)
|
||||
add_subdirectory(changeset)
|
||||
add_subdirectory(cplusplus)
|
||||
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