Android: fix avdmanager parsing error for some new device types

Currently avdmanager tool can give an error
"Error: Google <device> no longer exists as a device", due to missing
definition for new devices in device.xml.

This change temporarily removes the tag "hw.device.manufacturer" to
parse successfully, then recover it back.

Task-number: QTCREATORBUG-23284
Change-Id: I9c6f4b432d7c5d16944c9b620c4a4ecda473d45a
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
Assam Boudjelthia
2019-12-20 16:53:21 +02:00
parent 67bb2ebbae
commit 6a5b182706

View File

@@ -378,14 +378,60 @@ 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;
if (!avdManagerCommand(config, {"list", "avd"}, &output)) {
qCDebug(avdManagerLog) << "Avd list command failed" << output << config.sdkToolsVersion();
return {};
}
return parseAvdList(output);
AndroidDeviceInfoList avdList;
do {
if (!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 : avdErrorPaths)
AvdConfigEditManufacturerTag(avdPathStr, true);
return avdList;
}
AndroidDeviceInfoList AvdManagerOutputParser::parseAvdList(const QString &output)
@@ -394,7 +440,15 @@ AndroidDeviceInfoList AvdManagerOutputParser::parseAvdList(const QString &output
QStringList avdInfo;
auto parseAvdInfo = [&avdInfo, &avdList, this] () {
AndroidDeviceInfo avd;
if (parseAvd(avdInfo, &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("armeabi-v7a"))
avd.cpuAbi << "armeabi";
@@ -407,12 +461,11 @@ AndroidDeviceInfoList AvdManagerOutputParser::parseAvdList(const QString &output
avdInfo.clear();
};
foreach (QString line, output.split('\n')) {
if (line.startsWith("---------") || line.isEmpty()) {
for (const QString &line : output.split('\n')) {
if (line.startsWith("---------") || line.isEmpty())
parseAvdInfo();
} else {
else
avdInfo << line;
}
}
if (!avdInfo.isEmpty())
@@ -426,7 +479,7 @@ AndroidDeviceInfoList AvdManagerOutputParser::parseAvdList(const QString &output
bool AvdManagerOutputParser::parseAvd(const QStringList &deviceInfo, AndroidDeviceInfo *avd)
{
QTC_ASSERT(avd, return false);
foreach (const QString &line, deviceInfo) {
for (const QString &line : deviceInfo) {
QString value;
if (valueForKey(avdInfoErrorKey, line)) {
qCDebug(avdManagerLog) << "Avd Parsing: Skip avd device. Error key found:" << line;