Merge remote-tracking branch 'origin/4.7'

Conflicts:
	qbs/modules/qtc/qtc.qbs
	qtcreator.pri
	src/plugins/android/androiddebugsupport.cpp

Change-Id: I01c4880850ad25432a65bb32849365d2aeb0756f
This commit is contained in:
Eike Ziller
2018-07-10 07:44:53 +02:00
31 changed files with 369 additions and 109 deletions

View File

@@ -61,17 +61,43 @@
#include <QApplication>
#include <QDomDocument>
#include <QVersionNumber>
namespace {
Q_LOGGING_CATEGORY(androidManagerLog, "qtc.android.androidManager")
}
#include <QRegularExpression>
namespace {
const QLatin1String AndroidManifestName("AndroidManifest.xml");
const QLatin1String AndroidDefaultPropertiesName("project.properties");
const QLatin1String AndroidDeviceSn("AndroidDeviceSerialNumber");
const QLatin1String ApiLevelKey("AndroidVersion.ApiLevel");
const QString packageNameRegEx("(package: name=)\\'(([a-z]{1}[a-z\\d_]*\\."
")*[a-z][a-z\\d_]*)\\'");
const QString activityRegEx("(launchable-activity: name=)\\'"
"(([a-z]{1}[a-z\\d_]*\\.)*[a-z][a-z\\d_]*)\\'");
const QString apkVersionRegEx("package: name=([\\=a-z\\d_\\.\\'\\s]*)"
"\\sversionName='([\\d\\.]*)'");
Q_LOGGING_CATEGORY(androidManagerLog, "qtc.android.androidManager")
bool runCommand(const QString &executable, const QStringList &args,
QString *output = nullptr, int timeoutS = 30)
{
Utils::SynchronousProcess cmdProc;
cmdProc.setTimeoutS(timeoutS);
qCDebug(androidManagerLog) << executable << args.join(' ');
Utils::SynchronousProcessResponse response = cmdProc.runBlocking(executable, args);
if (output)
*output = response.allOutput();
return response.result == Utils::SynchronousProcessResponse::Finished;
}
QString parseAaptOutput(const QString &output, const QString &regEx) {
const QRegularExpression regRx(regEx,
QRegularExpression::CaseInsensitiveOption |
QRegularExpression::MultilineOption);
QRegularExpressionMatch match = regRx.match(output);
if (match.hasMatch())
return match.captured(2);
return QString();
};
} // anonymous namespace
@@ -127,6 +153,53 @@ QString AndroidManager::packageName(const Utils::FileName &manifestFile)
return manifestElem.attribute(QLatin1String("package"));
}
bool AndroidManager::packageInstalled(const QString &deviceSerial,
const QString &packageName)
{
if (deviceSerial.isEmpty() || packageName.isEmpty())
return false;
QStringList args = AndroidDeviceInfo::adbSelector(deviceSerial);
args << "shell" << "pm" << "list" << "packages";
QString output;
runAdbCommand(args, &output);
QStringList lines = output.split(QRegularExpression("[\\n\\r]"),
QString::SkipEmptyParts);
for (const QString &line : lines) {
// Don't want to confuse com.abc.xyz with com.abc.xyz.def so check with
// endsWith
if (line.endsWith(packageName))
return true;
}
return false;
}
void AndroidManager::apkInfo(const Utils::FileName &apkPath,
QString *packageName,
QVersionNumber *version,
QString *activityPath)
{
QString output;
runAaptCommand({"dump", "badging", apkPath.toString()}, &output);
QString packageStr;
if (activityPath) {
packageStr = parseAaptOutput(output, packageNameRegEx);
QString path = parseAaptOutput(output, activityRegEx);
if (!packageStr.isEmpty() && !path.isEmpty())
*activityPath = packageStr + '/' + path;
}
if (packageName) {
*packageName = activityPath ? packageStr :
parseAaptOutput(output, packageNameRegEx);
}
if (version) {
QString versionStr = parseAaptOutput(output, apkVersionRegEx);
*version = QVersionNumber::fromString(versionStr);
}
}
QString AndroidManager::intentName(ProjectExplorer::Target *target)
{
return packageName(target) + QLatin1Char('/') + activityName(target);
@@ -381,16 +454,9 @@ void AndroidManager::cleanLibsOnDevice(ProjectExplorer::Target *target)
Core::MessageManager::write(tr("Starting Android virtual device failed."));
}
QProcess *process = new QProcess();
QStringList arguments = AndroidDeviceInfo::adbSelector(deviceSerialNumber);
arguments << QLatin1String("shell") << QLatin1String("rm") << QLatin1String("-r") << QLatin1String("/data/local/tmp/qt");
QObject::connect(process, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
process, &QObject::deleteLater);
const QString adb = AndroidConfigurations::currentConfig().adbToolPath().toString();
Core::MessageManager::write(adb + QLatin1Char(' ') + arguments.join(QLatin1Char(' ')));
process->start(adb, arguments);
if (!process->waitForStarted(500))
delete process;
runAdbCommandDetached(arguments);
}
void AndroidManager::installQASIPackage(ProjectExplorer::Target *target, const QString &packagePath)
@@ -410,17 +476,9 @@ void AndroidManager::installQASIPackage(ProjectExplorer::Target *target, const Q
Core::MessageManager::write(tr("Starting Android virtual device failed."));
}
QProcess *process = new QProcess();
QStringList arguments = AndroidDeviceInfo::adbSelector(deviceSerialNumber);
arguments << QLatin1String("install") << QLatin1String("-r ") << packagePath;
connect(process, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
process, &QObject::deleteLater);
const QString adb = AndroidConfigurations::currentConfig().adbToolPath().toString();
Core::MessageManager::write(adb + QLatin1Char(' ') + arguments.join(QLatin1Char(' ')));
process->start(adb, arguments);
if (!process->waitForStarted(500) && process->state() != QProcess::Running)
delete process;
runAdbCommandDetached(arguments);
}
bool AndroidManager::checkKeystorePassword(const QString &keystorePath, const QString &keystorePasswd)
@@ -603,4 +661,27 @@ int AndroidManager::findApiLevel(const Utils::FileName &platformPath)
return apiLevel;
}
void AndroidManager::runAdbCommandDetached(const QStringList &args)
{
QProcess *process = new QProcess();
connect(process, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
process, &QObject::deleteLater);
const QString adb = AndroidConfigurations::currentConfig().adbToolPath().toString();
qCDebug(androidManagerLog) << adb << args.join(' ');
process->start(adb, args);
if (!process->waitForStarted(500) && process->state() != QProcess::Running)
delete process;
}
bool AndroidManager::runAdbCommand(const QStringList &args, QString *output)
{
return runCommand(AndroidConfigurations::currentConfig().adbToolPath().toString(),
args, output);
}
bool AndroidManager::runAaptCommand(const QStringList &args, QString *output)
{
return runCommand(AndroidConfigurations::currentConfig().aaptToolPath().toString(),
args, output);
}
} // namespace Android