forked from qt-creator/qt-creator
Add AndroidRunnable
Using the AndroidRunnable is easy for other plugins to run custom adb commands before intent is started and after it's stopped. Change-Id: I012ae87c92cea16aa8074dce2dc6f2b0c4ebeb30 Reviewed-by: hjk <hjk@theqtcompany.com>
This commit is contained in:
@@ -47,7 +47,8 @@ HEADERS += \
|
|||||||
avddialog.h \
|
avddialog.h \
|
||||||
android_global.h \
|
android_global.h \
|
||||||
androidbuildapkstep.h \
|
androidbuildapkstep.h \
|
||||||
androidbuildapkwidget.h
|
androidbuildapkwidget.h \
|
||||||
|
androidrunnable.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
androidconfigurations.cpp \
|
androidconfigurations.cpp \
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ QtcPlugin {
|
|||||||
"androidruncontrol.h",
|
"androidruncontrol.h",
|
||||||
"androidrunfactories.cpp",
|
"androidrunfactories.cpp",
|
||||||
"androidrunfactories.h",
|
"androidrunfactories.h",
|
||||||
|
"androidrunnable.h",
|
||||||
"androidrunner.cpp",
|
"androidrunner.cpp",
|
||||||
"androidrunner.h",
|
"androidrunner.h",
|
||||||
"androidsettingspage.cpp",
|
"androidsettingspage.cpp",
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ AndroidRunControl::AndroidRunControl(AndroidRunConfiguration *rc)
|
|||||||
, m_runner(new AndroidRunner(this, rc, ProjectExplorer::Constants::NORMAL_RUN_MODE))
|
, m_runner(new AndroidRunner(this, rc, ProjectExplorer::Constants::NORMAL_RUN_MODE))
|
||||||
, m_running(false)
|
, m_running(false)
|
||||||
{
|
{
|
||||||
|
setRunnable(m_runner->runnable());
|
||||||
setIcon(Icons::RUN_SMALL);
|
setIcon(Icons::RUN_SMALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +64,7 @@ void AndroidRunControl::start()
|
|||||||
connect(m_runner, SIGNAL(remoteProcessFinished(QString)),
|
connect(m_runner, SIGNAL(remoteProcessFinished(QString)),
|
||||||
SLOT(handleRemoteProcessFinished(QString)));
|
SLOT(handleRemoteProcessFinished(QString)));
|
||||||
appendMessage(tr("Starting remote process."), Utils::NormalMessageFormat);
|
appendMessage(tr("Starting remote process."), Utils::NormalMessageFormat);
|
||||||
|
m_runner->setRunnable(runnable().as<AndroidRunnable>());
|
||||||
m_runner->start();
|
m_runner->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
47
src/plugins/android/androidrunnable.h
Normal file
47
src/plugins/android/androidrunnable.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef ANDROIDRUNNABLE_H
|
||||||
|
#define ANDROIDRUNNABLE_H
|
||||||
|
|
||||||
|
#include "android_global.h"
|
||||||
|
#include <projectexplorer/runnables.h>
|
||||||
|
|
||||||
|
namespace Android {
|
||||||
|
|
||||||
|
struct ANDROID_EXPORT AndroidRunnable
|
||||||
|
{
|
||||||
|
QString packageName;
|
||||||
|
QString intentName;
|
||||||
|
QString commandLineArguments;
|
||||||
|
Utils::Environment environment;
|
||||||
|
QVector<QStringList> beforeStartADBCommands;
|
||||||
|
QVector<QStringList> afterFinishADBCommands;
|
||||||
|
QString deviceSerialNumber;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Android
|
||||||
|
|
||||||
|
#endif // ANDROIDRUNNABLE_H
|
||||||
@@ -149,17 +149,17 @@ AndroidRunner::AndroidRunner(QObject *parent,
|
|||||||
m_qmlPort = 0;
|
m_qmlPort = 0;
|
||||||
}
|
}
|
||||||
ProjectExplorer::Target *target = runConfig->target();
|
ProjectExplorer::Target *target = runConfig->target();
|
||||||
m_intentName = AndroidManager::intentName(target);
|
m_androidRunnable.intentName = AndroidManager::intentName(target);
|
||||||
m_packageName = m_intentName.left(m_intentName.indexOf(QLatin1Char('/')));
|
m_androidRunnable.packageName = m_androidRunnable.intentName.left(m_androidRunnable.intentName.indexOf(QLatin1Char('/')));
|
||||||
|
|
||||||
m_deviceSerialNumber = AndroidManager::deviceSerialNumber(target);
|
m_androidRunnable.deviceSerialNumber = AndroidManager::deviceSerialNumber(target);
|
||||||
m_processPID = -1;
|
m_processPID = -1;
|
||||||
m_adb = AndroidConfigurations::currentConfig().adbToolPath().toString();
|
m_adb = AndroidConfigurations::currentConfig().adbToolPath().toString();
|
||||||
m_selector = AndroidDeviceInfo::adbSelector(m_deviceSerialNumber);
|
m_selector = AndroidDeviceInfo::adbSelector(m_androidRunnable.deviceSerialNumber);
|
||||||
|
|
||||||
QString packageDir = _("/data/data/") + m_packageName;
|
QString packageDir = _("/data/data/") + m_androidRunnable.packageName;
|
||||||
m_pingFile = packageDir + _("/debug-ping");
|
m_pingFile = packageDir + _("/debug-ping");
|
||||||
m_pongFile = _("/data/local/tmp/qt/debug-pong-") + m_packageName;
|
m_pongFile = _("/data/local/tmp/qt/debug-pong-") + m_androidRunnable.packageName;
|
||||||
m_gdbserverSocket = packageDir + _("/debug-socket");
|
m_gdbserverSocket = packageDir + _("/debug-socket");
|
||||||
const QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target->kit());
|
const QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target->kit());
|
||||||
if (version && version->qtVersion() >= QtSupport::QtVersionNumber(5, 4, 0))
|
if (version && version->qtVersion() >= QtSupport::QtVersionNumber(5, 4, 0))
|
||||||
@@ -263,16 +263,16 @@ QByteArray AndroidRunner::runPs()
|
|||||||
void AndroidRunner::checkPID()
|
void AndroidRunner::checkPID()
|
||||||
{
|
{
|
||||||
QByteArray psOut = runPs();
|
QByteArray psOut = runPs();
|
||||||
m_processPID = extractPid(m_packageName, psOut);
|
m_processPID = extractPid(m_androidRunnable.packageName, psOut);
|
||||||
|
|
||||||
if (m_processPID == -1) {
|
if (m_processPID == -1) {
|
||||||
if (m_wasStarted) {
|
if (m_wasStarted) {
|
||||||
m_wasStarted = false;
|
m_wasStarted = false;
|
||||||
m_checkPIDTimer.stop();
|
m_checkPIDTimer.stop();
|
||||||
emit remoteProcessFinished(QLatin1String("\n\n") + tr("\"%1\" died.").arg(m_packageName));
|
emit remoteProcessFinished(QLatin1String("\n\n") + tr("\"%1\" died.").arg(m_androidRunnable.packageName));
|
||||||
} else {
|
} else {
|
||||||
if (++m_tries > 3)
|
if (++m_tries > 3)
|
||||||
emit remoteProcessFinished(QLatin1String("\n\n") + tr("Unable to start \"%1\".").arg(m_packageName));
|
emit remoteProcessFinished(QLatin1String("\n\n") + tr("Unable to start \"%1\".").arg(m_androidRunnable.packageName));
|
||||||
}
|
}
|
||||||
} else if (!m_wasStarted){
|
} else if (!m_wasStarted){
|
||||||
if (m_useCppDebugger) {
|
if (m_useCppDebugger) {
|
||||||
@@ -300,7 +300,7 @@ void AndroidRunner::forceStop()
|
|||||||
{
|
{
|
||||||
QProcess proc;
|
QProcess proc;
|
||||||
proc.start(m_adb, selector() << _("shell") << _("am") << _("force-stop")
|
proc.start(m_adb, selector() << _("shell") << _("am") << _("force-stop")
|
||||||
<< m_packageName);
|
<< m_androidRunnable.packageName);
|
||||||
proc.waitForFinished();
|
proc.waitForFinished();
|
||||||
|
|
||||||
// try killing it via kill -9
|
// try killing it via kill -9
|
||||||
@@ -311,7 +311,7 @@ void AndroidRunner::forceStop()
|
|||||||
if (to == -1)
|
if (to == -1)
|
||||||
break;
|
break;
|
||||||
QString line = QString::fromUtf8(out.data() + from, to - from - 1);
|
QString line = QString::fromUtf8(out.data() + from, to - from - 1);
|
||||||
if (line.endsWith(m_packageName) || line.endsWith(m_gdbserverPath)) {
|
if (line.endsWith(m_androidRunnable.packageName) || line.endsWith(m_gdbserverPath)) {
|
||||||
int pid = extractPidFromChunk(out, from);
|
int pid = extractPidFromChunk(out, from);
|
||||||
adbKill(pid);
|
adbKill(pid);
|
||||||
}
|
}
|
||||||
@@ -337,8 +337,14 @@ void AndroidRunner::asyncStart()
|
|||||||
adb.waitForFinished();
|
adb.waitForFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (const QStringList &entry, m_androidRunnable.beforeStartADBCommands) {
|
||||||
|
QProcess adb;
|
||||||
|
adb.start(m_adb, selector() << entry);
|
||||||
|
adb.waitForFinished();
|
||||||
|
}
|
||||||
|
|
||||||
QStringList args = selector();
|
QStringList args = selector();
|
||||||
args << _("shell") << _("am") << _("start") << _("-n") << m_intentName;
|
args << _("shell") << _("am") << _("start") << _("-n") << m_androidRunnable.intentName;
|
||||||
|
|
||||||
if (m_useCppDebugger) {
|
if (m_useCppDebugger) {
|
||||||
QProcess adb;
|
QProcess adb;
|
||||||
@@ -354,7 +360,7 @@ void AndroidRunner::asyncStart()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString pingPongSocket(m_packageName + _(".ping_pong_socket"));
|
const QString pingPongSocket(m_androidRunnable.packageName + _(".ping_pong_socket"));
|
||||||
args << _("-e") << _("debug_ping") << _("true");
|
args << _("-e") << _("debug_ping") << _("true");
|
||||||
if (m_handShakeMethod == SocketHandShake) {
|
if (m_handShakeMethod == SocketHandShake) {
|
||||||
args << _("-e") << _("ping_socket") << pingPongSocket;
|
args << _("-e") << _("ping_socket") << pingPongSocket;
|
||||||
@@ -411,7 +417,7 @@ void AndroidRunner::asyncStart()
|
|||||||
}
|
}
|
||||||
if (!adb.waitForFinished(10000)) {
|
if (!adb.waitForFinished(10000)) {
|
||||||
adb.terminate();
|
adb.terminate();
|
||||||
emit remoteProcessFinished(tr("Unable to start \"%1\".").arg(m_packageName));
|
emit remoteProcessFinished(tr("Unable to start \"%1\".").arg(m_androidRunnable.packageName));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,7 +482,7 @@ void AndroidRunner::asyncStart()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (i == 20) {
|
if (i == 20) {
|
||||||
emit remoteProcessFinished(tr("Unable to start \"%1\".").arg(m_packageName));
|
emit remoteProcessFinished(tr("Unable to start \"%1\".").arg(m_androidRunnable.packageName));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
qDebug() << "WAITING FOR " << tmp.fileName();
|
qDebug() << "WAITING FOR " << tmp.fileName();
|
||||||
@@ -540,11 +546,16 @@ void AndroidRunner::stop()
|
|||||||
m_tries = 0;
|
m_tries = 0;
|
||||||
if (m_processPID != -1) {
|
if (m_processPID != -1) {
|
||||||
forceStop();
|
forceStop();
|
||||||
emit remoteProcessFinished(QLatin1String("\n\n") + tr("\"%1\" terminated.").arg(m_packageName));
|
emit remoteProcessFinished(QLatin1String("\n\n") + tr("\"%1\" terminated.").arg(m_androidRunnable.packageName));
|
||||||
}
|
}
|
||||||
//QObject::disconnect(&m_adbLogcatProcess, 0, this, 0);
|
//QObject::disconnect(&m_adbLogcatProcess, 0, this, 0);
|
||||||
m_adbLogcatProcess.kill();
|
m_adbLogcatProcess.kill();
|
||||||
m_adbLogcatProcess.waitForFinished();
|
m_adbLogcatProcess.waitForFinished();
|
||||||
|
foreach (const QStringList &entry, m_androidRunnable.afterFinishADBCommands) {
|
||||||
|
QProcess adb;
|
||||||
|
adb.start(m_adb, selector() << entry);
|
||||||
|
adb.waitForFinished();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidRunner::logcatProcess(const QByteArray &text, QByteArray &buffer, bool onlyError)
|
void AndroidRunner::logcatProcess(const QByteArray &text, QByteArray &buffer, bool onlyError)
|
||||||
@@ -613,7 +624,7 @@ void AndroidRunner::adbKill(qint64 pid)
|
|||||||
{
|
{
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.start(m_adb, selector() << _("shell")
|
process.start(m_adb, selector() << _("shell")
|
||||||
<< _("run-as") << m_packageName
|
<< _("run-as") << m_androidRunnable.packageName
|
||||||
<< _("kill") << QLatin1String("-9") << QString::number(pid));
|
<< _("kill") << QLatin1String("-9") << QString::number(pid));
|
||||||
process.waitForFinished();
|
process.waitForFinished();
|
||||||
}
|
}
|
||||||
@@ -621,7 +632,13 @@ void AndroidRunner::adbKill(qint64 pid)
|
|||||||
|
|
||||||
QString AndroidRunner::displayName() const
|
QString AndroidRunner::displayName() const
|
||||||
{
|
{
|
||||||
return m_packageName;
|
return m_androidRunnable.packageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidRunner::setRunnable(const AndroidRunnable &runnable)
|
||||||
|
{
|
||||||
|
m_androidRunnable = runnable;
|
||||||
|
m_selector = AndroidDeviceInfo::adbSelector(m_androidRunnable.deviceSerialNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#define ANDROIDRUNNER_H
|
#define ANDROIDRUNNER_H
|
||||||
|
|
||||||
#include "androidconfigurations.h"
|
#include "androidconfigurations.h"
|
||||||
|
#include "androidrunnable.h"
|
||||||
|
|
||||||
#include <projectexplorer/runconfiguration.h>
|
#include <projectexplorer/runconfiguration.h>
|
||||||
#include <qmldebug/qmldebugcommandlinearguments.h>
|
#include <qmldebug/qmldebugcommandlinearguments.h>
|
||||||
@@ -58,6 +59,8 @@ public:
|
|||||||
~AndroidRunner();
|
~AndroidRunner();
|
||||||
|
|
||||||
QString displayName() const;
|
QString displayName() const;
|
||||||
|
void setRunnable(const AndroidRunnable &runnable);
|
||||||
|
const AndroidRunnable &runnable() const { return m_androidRunnable; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void start();
|
void start();
|
||||||
@@ -92,12 +95,9 @@ private:
|
|||||||
QTimer m_checkPIDTimer;
|
QTimer m_checkPIDTimer;
|
||||||
bool m_wasStarted;
|
bool m_wasStarted;
|
||||||
int m_tries;
|
int m_tries;
|
||||||
|
|
||||||
QByteArray m_stdoutBuffer;
|
QByteArray m_stdoutBuffer;
|
||||||
QByteArray m_stderrBuffer;
|
QByteArray m_stderrBuffer;
|
||||||
QString m_intentName;
|
AndroidRunnable m_androidRunnable;
|
||||||
QString m_packageName;
|
|
||||||
QString m_deviceSerialNumber;
|
|
||||||
qint64 m_processPID;
|
qint64 m_processPID;
|
||||||
bool m_useCppDebugger;
|
bool m_useCppDebugger;
|
||||||
QmlDebug::QmlDebugServicesPreset m_qmlDebugServices;
|
QmlDebug::QmlDebugServicesPreset m_qmlDebugServices;
|
||||||
|
|||||||
Reference in New Issue
Block a user