forked from qt-creator/qt-creator
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:
@@ -378,14 +378,60 @@ 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 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)
|
AndroidDeviceInfoList AvdManagerOutputParser::listVirtualDevices(const AndroidConfig &config)
|
||||||
{
|
{
|
||||||
QString output;
|
QString output;
|
||||||
if (!avdManagerCommand(config, {"list", "avd"}, &output)) {
|
AndroidDeviceInfoList avdList;
|
||||||
qCDebug(avdManagerLog) << "Avd list command failed" << output << config.sdkToolsVersion();
|
|
||||||
return {};
|
do {
|
||||||
}
|
if (!avdManagerCommand(config, {"list", "avd"}, &output)) {
|
||||||
return parseAvdList(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)
|
AndroidDeviceInfoList AvdManagerOutputParser::parseAvdList(const QString &output)
|
||||||
@@ -394,7 +440,15 @@ AndroidDeviceInfoList AvdManagerOutputParser::parseAvdList(const QString &output
|
|||||||
QStringList avdInfo;
|
QStringList avdInfo;
|
||||||
auto parseAvdInfo = [&avdInfo, &avdList, this] () {
|
auto parseAvdInfo = [&avdInfo, &avdList, this] () {
|
||||||
AndroidDeviceInfo avd;
|
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
|
// armeabi-v7a devices can also run armeabi code
|
||||||
if (avd.cpuAbi.contains("armeabi-v7a"))
|
if (avd.cpuAbi.contains("armeabi-v7a"))
|
||||||
avd.cpuAbi << "armeabi";
|
avd.cpuAbi << "armeabi";
|
||||||
@@ -407,12 +461,11 @@ AndroidDeviceInfoList AvdManagerOutputParser::parseAvdList(const QString &output
|
|||||||
avdInfo.clear();
|
avdInfo.clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (QString line, output.split('\n')) {
|
for (const QString &line : output.split('\n')) {
|
||||||
if (line.startsWith("---------") || line.isEmpty()) {
|
if (line.startsWith("---------") || line.isEmpty())
|
||||||
parseAvdInfo();
|
parseAvdInfo();
|
||||||
} else {
|
else
|
||||||
avdInfo << line;
|
avdInfo << line;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!avdInfo.isEmpty())
|
if (!avdInfo.isEmpty())
|
||||||
@@ -426,7 +479,7 @@ AndroidDeviceInfoList AvdManagerOutputParser::parseAvdList(const QString &output
|
|||||||
bool AvdManagerOutputParser::parseAvd(const QStringList &deviceInfo, AndroidDeviceInfo *avd)
|
bool AvdManagerOutputParser::parseAvd(const QStringList &deviceInfo, AndroidDeviceInfo *avd)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(avd, return false);
|
QTC_ASSERT(avd, return false);
|
||||||
foreach (const QString &line, deviceInfo) {
|
for (const QString &line : deviceInfo) {
|
||||||
QString value;
|
QString value;
|
||||||
if (valueForKey(avdInfoErrorKey, line)) {
|
if (valueForKey(avdInfoErrorKey, line)) {
|
||||||
qCDebug(avdManagerLog) << "Avd Parsing: Skip avd device. Error key found:" << line;
|
qCDebug(avdManagerLog) << "Avd Parsing: Skip avd device. Error key found:" << line;
|
||||||
|
|||||||
Reference in New Issue
Block a user