Android: Run all of AndroidRunner in a separate thread

This removes the need for blocking queued connections and runAsync(),
reducing the risk of deadlocks and eliminating unguarded concurrent
access to various members of AndroidRunner. No mutex locking is
necessary anymore as all communication between the two threads is
either done on initialization, before the worker thread starts, or
via queued signals.

Change-Id: Icc2fcc2c0ce73d1c226bc4740413e57490d1cbc6
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
Ulf Hermann
2016-08-05 15:40:33 +02:00
parent 8c5dd4ad49
commit 5f950a80cc
4 changed files with 326 additions and 223 deletions

View File

@@ -44,15 +44,11 @@ class AndroidRunConfiguration;
namespace Internal {
class AndroidRunnerWorker;
class AndroidRunner : public QObject
{
Q_OBJECT
enum DebugHandShakeType {
PingPongFiles,
SocketHandShake
};
public:
AndroidRunner(QObject *parent, AndroidRunConfiguration *runConfig,
Core::Id runMode);
@@ -62,63 +58,34 @@ public:
void setRunnable(const AndroidRunnable &runnable);
const AndroidRunnable &runnable() const { return m_androidRunnable; }
public:
void start();
void stop();
void handleRemoteDebuggerRunning();
signals:
void remoteServerRunning(const QByteArray &serverChannel, int pid);
void remoteProcessStarted(Utils::Port gdbServerPort, Utils::Port qmlPort);
void remoteProcessFinished(const QString &errString = QString());
void remoteDebuggerRunning();
void remoteOutput(const QString &output);
void remoteErrorOutput(const QString &output);
void asyncStart(const QString &intentName, const QVector<QStringList> &adbCommands);
void asyncStop(const QVector<QStringList> &adbCommands);
void adbParametersChanged(const QString &packageName, const QStringList &selector);
void avdDetected();
private:
void checkPID();
void logcatReadStandardError();
void logcatReadStandardOutput();
void asyncStart();
void asyncStop();
Q_INVOKABLE void launchAVDProcesses();
void adbKill(qint64 pid);
QStringList selector() const { return m_selector; }
void forceStop();
void findPs();
void logcatProcess(const QByteArray &text, QByteArray &buffer, bool onlyError);
bool adbShellAmNeedsQuotes();
void checkAVD();
void launchAVD();
bool runAdb(const QStringList &args, QString *errorMessage = nullptr, int timeoutS = 10);
private:
AndroidRunnable m_androidRunnable;
AndroidRunConfiguration *m_runConfig;
QString m_launchedAVDName;
QFutureInterface<bool> m_avdFutureInterface;
QProcess m_adbLogcatProcess;
QProcess m_psProc;
QTimer m_checkPIDTimer;
bool m_wasStarted;
int m_tries;
QByteArray m_stdoutBuffer;
QByteArray m_stderrBuffer;
AndroidRunnable m_androidRunnable;
qint64 m_processPID;
bool m_useCppDebugger;
QmlDebug::QmlDebugServicesPreset m_qmlDebugServices;
Utils::Port m_localGdbServerPort; // Local end of forwarded debug socket.
Utils::Port m_qmlPort;
QString m_pingFile;
QString m_pongFile;
QString m_gdbserverPath;
QString m_gdbserverSocket;
QString m_adb;
bool m_isBusyBox;
QStringList m_selector;
QMutex m_mutex;
QRegExp m_logCatRegExp;
DebugHandShakeType m_handShakeMethod = SocketHandShake;
QTcpSocket *m_socket;
bool m_customPort;
QThread m_thread;
QTimer m_checkAVDTimer;
QScopedPointer<AndroidRunnerWorker> m_worker;
};
} // namespace Internal