forked from qt-creator/qt-creator
Android: Let user specify shell commands
Let user specify list of shell commands to run before app starts and after app quits. Change-Id: I9794fb96180530ca6c28ce6581fda51a25be28d4 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
198
src/plugins/android/adbcommandswidget.cpp
Normal file
198
src/plugins/android/adbcommandswidget.cpp
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2017 The Qt Company Ltd.
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#include "adbcommandswidget.h"
|
||||||
|
#include "ui_adbcommandswidget.h"
|
||||||
|
|
||||||
|
#include "utils/utilsicons.h"
|
||||||
|
|
||||||
|
#include <QGroupBox>
|
||||||
|
#include <QItemSelectionModel>
|
||||||
|
#include <QShortcut>
|
||||||
|
#include <QStringListModel>
|
||||||
|
|
||||||
|
namespace Android {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
const char defaultCommand[] = "echo \"shell command\"";
|
||||||
|
|
||||||
|
static void swapData(QStringListModel *model, const QModelIndex &srcIndex,
|
||||||
|
const QModelIndex &destIndex)
|
||||||
|
{
|
||||||
|
if (model) {
|
||||||
|
QVariant data = model->data(destIndex, Qt::EditRole); // QTBUG-55078
|
||||||
|
model->setData(destIndex, model->data(srcIndex, Qt::EditRole));
|
||||||
|
model->setData(srcIndex, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AdbCommandsWidgetPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AdbCommandsWidgetPrivate(const AdbCommandsWidget &parent, QWidget *parentWidget);
|
||||||
|
~AdbCommandsWidgetPrivate();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void addString(const QString &str);
|
||||||
|
void onAddButton();
|
||||||
|
void onMoveUpButton();
|
||||||
|
void onMoveDownButton();
|
||||||
|
void onRemove();
|
||||||
|
void onCurrentIndexChanged(const QModelIndex &newIndex, const QModelIndex &prevIndex);
|
||||||
|
|
||||||
|
const AdbCommandsWidget &m_parent;
|
||||||
|
QGroupBox *m_rootWidget = nullptr;
|
||||||
|
Ui::AdbCommandsWidget *m_ui = nullptr;
|
||||||
|
QStringListModel *m_stringModel = nullptr;
|
||||||
|
friend class AdbCommandsWidget;
|
||||||
|
};
|
||||||
|
|
||||||
|
AdbCommandsWidget::AdbCommandsWidget(QWidget *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
d(new AdbCommandsWidgetPrivate(*this, parent))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AdbCommandsWidget::~AdbCommandsWidget()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList AdbCommandsWidget::commandsList() const
|
||||||
|
{
|
||||||
|
return d->m_stringModel->stringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *AdbCommandsWidget::widget() const
|
||||||
|
{
|
||||||
|
return d->m_rootWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdbCommandsWidget::setTitleText(const QString &title)
|
||||||
|
{
|
||||||
|
d->m_rootWidget->setTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdbCommandsWidget::setCommandList(const QStringList &commands)
|
||||||
|
{
|
||||||
|
d->m_stringModel->setStringList(commands);
|
||||||
|
}
|
||||||
|
|
||||||
|
AdbCommandsWidgetPrivate::AdbCommandsWidgetPrivate(const AdbCommandsWidget &parent,
|
||||||
|
QWidget *parentWidget):
|
||||||
|
m_parent(parent),
|
||||||
|
m_rootWidget(new QGroupBox(parentWidget)),
|
||||||
|
m_ui(new Ui::AdbCommandsWidget),
|
||||||
|
m_stringModel(new QStringListModel)
|
||||||
|
{
|
||||||
|
m_ui->setupUi(m_rootWidget);
|
||||||
|
m_ui->addButton->setIcon(Utils::Icons::PLUS.icon());
|
||||||
|
m_ui->removeButton->setIcon(Utils::Icons::MINUS.icon());
|
||||||
|
m_ui->moveUpButton->setIcon(Utils::Icons::ARROW_UP.icon());
|
||||||
|
m_ui->moveDownButton->setIcon(Utils::Icons::ARROW_DOWN.icon());
|
||||||
|
|
||||||
|
auto deleteShortcut = new QShortcut(QKeySequence(QKeySequence::Delete), m_ui->commandsView);
|
||||||
|
deleteShortcut->setContext(Qt::WidgetShortcut);
|
||||||
|
QObject::connect(deleteShortcut, &QShortcut::activated,
|
||||||
|
std::bind(&AdbCommandsWidgetPrivate::onRemove, this));
|
||||||
|
|
||||||
|
QObject::connect(m_ui->addButton, &QToolButton::clicked,
|
||||||
|
std::bind(&AdbCommandsWidgetPrivate::onAddButton, this));
|
||||||
|
QObject::connect(m_ui->removeButton, &QToolButton::clicked,
|
||||||
|
std::bind(&AdbCommandsWidgetPrivate::onRemove, this));
|
||||||
|
QObject::connect(m_ui->moveUpButton, &QToolButton::clicked,
|
||||||
|
std::bind(&AdbCommandsWidgetPrivate::onMoveUpButton, this));
|
||||||
|
QObject::connect(m_ui->moveDownButton, &QToolButton::clicked,
|
||||||
|
std::bind(&AdbCommandsWidgetPrivate::onMoveDownButton, this));
|
||||||
|
|
||||||
|
m_ui->commandsView->setModel(m_stringModel);
|
||||||
|
QObject::connect(m_stringModel, &QStringListModel::dataChanged,
|
||||||
|
&m_parent, &AdbCommandsWidget::commandsChanged);
|
||||||
|
QObject::connect(m_stringModel, &QStringListModel::rowsRemoved,
|
||||||
|
&m_parent, &AdbCommandsWidget::commandsChanged);
|
||||||
|
QObject::connect(m_ui->commandsView->selectionModel(), &QItemSelectionModel::currentChanged,
|
||||||
|
std::bind(&AdbCommandsWidgetPrivate::onCurrentIndexChanged, this, _1, _2));
|
||||||
|
}
|
||||||
|
|
||||||
|
AdbCommandsWidgetPrivate::~AdbCommandsWidgetPrivate()
|
||||||
|
{
|
||||||
|
delete m_ui;
|
||||||
|
delete m_stringModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdbCommandsWidgetPrivate::addString(const QString &str)
|
||||||
|
{
|
||||||
|
if (!str.isEmpty()) {
|
||||||
|
m_stringModel->insertRows(m_stringModel->rowCount(), 1);
|
||||||
|
const QModelIndex lastItemIndex = m_stringModel->index(m_stringModel->rowCount() - 1);
|
||||||
|
m_stringModel->setData(lastItemIndex, str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdbCommandsWidgetPrivate::onAddButton()
|
||||||
|
{
|
||||||
|
addString(defaultCommand);
|
||||||
|
const QModelIndex index = m_stringModel->index(m_stringModel->rowCount() - 1);
|
||||||
|
m_ui->commandsView->setCurrentIndex(index);
|
||||||
|
m_ui->commandsView->edit(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdbCommandsWidgetPrivate::onMoveUpButton()
|
||||||
|
{
|
||||||
|
QModelIndex index = m_ui->commandsView->currentIndex();
|
||||||
|
if (index.row() > 0) {
|
||||||
|
const QModelIndex newIndex = m_stringModel->index(index.row() - 1, 0);
|
||||||
|
swapData(m_stringModel, index, newIndex);
|
||||||
|
m_ui->commandsView->setCurrentIndex(newIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdbCommandsWidgetPrivate::onMoveDownButton()
|
||||||
|
{
|
||||||
|
QModelIndex index = m_ui->commandsView->currentIndex();
|
||||||
|
if (index.row() < m_stringModel->rowCount() - 1) {
|
||||||
|
const QModelIndex newIndex = m_stringModel->index(index.row() + 1, 0);
|
||||||
|
swapData(m_stringModel, index, newIndex);
|
||||||
|
m_ui->commandsView->setCurrentIndex(newIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdbCommandsWidgetPrivate::onRemove()
|
||||||
|
{
|
||||||
|
const QModelIndex &index = m_ui->commandsView->currentIndex();
|
||||||
|
if (index.isValid())
|
||||||
|
m_stringModel->removeRow(index.row());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdbCommandsWidgetPrivate::onCurrentIndexChanged(const QModelIndex &newIndex, const QModelIndex &prevIndex)
|
||||||
|
{
|
||||||
|
Q_UNUSED(prevIndex)
|
||||||
|
m_ui->moveUpButton->setEnabled(newIndex.row() != 0);
|
||||||
|
m_ui->moveDownButton->setEnabled(newIndex.row() < m_stringModel->rowCount() - 1);
|
||||||
|
m_ui->removeButton->setEnabled(newIndex.isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Internal
|
||||||
|
} // Android
|
64
src/plugins/android/adbcommandswidget.h
Normal file
64
src/plugins/android/adbcommandswidget.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2017 The Qt Company Ltd.
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QWidget;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Android {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class AdbCommandsWidgetPrivate;
|
||||||
|
|
||||||
|
class AdbCommandsWidget : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit AdbCommandsWidget(QWidget *parent);
|
||||||
|
~AdbCommandsWidget();
|
||||||
|
|
||||||
|
QStringList commandsList() const;
|
||||||
|
void setCommandList(const QStringList &commands);
|
||||||
|
|
||||||
|
QWidget *widget() const;
|
||||||
|
|
||||||
|
void setTitleText(const QString &title);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void commandsChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<AdbCommandsWidgetPrivate> d;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Internal
|
||||||
|
} // Android
|
117
src/plugins/android/adbcommandswidget.ui
Normal file
117
src/plugins/android/adbcommandswidget.ui
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>AdbCommandsWidget</class>
|
||||||
|
<widget class="QGroupBox" name="AdbCommandsWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>682</width>
|
||||||
|
<height>391</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Widget</string>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="2" column="1">
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" rowspan="6">
|
||||||
|
<widget class="QListView" name="commandsView">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="defaultDropAction">
|
||||||
|
<enum>Qt::MoveAction</enum>
|
||||||
|
</property>
|
||||||
|
<property name="movement">
|
||||||
|
<enum>QListView::Snap</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QToolButton" name="moveUpButton">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="arrowType">
|
||||||
|
<enum>Qt::NoArrow</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<spacer name="verticalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QToolButton" name="addButton">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QToolButton" name="moveDownButton">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="arrowType">
|
||||||
|
<enum>Qt::NoArrow</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QToolButton" name="removeButton">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>commandsView</tabstop>
|
||||||
|
<tabstop>addButton</tabstop>
|
||||||
|
<tabstop>removeButton</tabstop>
|
||||||
|
<tabstop>moveUpButton</tabstop>
|
||||||
|
<tabstop>moveDownButton</tabstop>
|
||||||
|
</tabstops>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@@ -50,7 +50,8 @@ HEADERS += \
|
|||||||
androidtoolmanager.h \
|
androidtoolmanager.h \
|
||||||
androidsdkmanager.h \
|
androidsdkmanager.h \
|
||||||
androidavdmanager.h \
|
androidavdmanager.h \
|
||||||
androidrunconfigurationwidget.h
|
androidrunconfigurationwidget.h \
|
||||||
|
adbcommandswidget.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
androidconfigurations.cpp \
|
androidconfigurations.cpp \
|
||||||
@@ -94,7 +95,8 @@ SOURCES += \
|
|||||||
androidtoolmanager.cpp \
|
androidtoolmanager.cpp \
|
||||||
androidsdkmanager.cpp \
|
androidsdkmanager.cpp \
|
||||||
androidavdmanager.cpp \
|
androidavdmanager.cpp \
|
||||||
androidrunconfigurationwidget.cpp
|
androidrunconfigurationwidget.cpp \
|
||||||
|
adbcommandswidget.cpp
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
androidsettingswidget.ui \
|
androidsettingswidget.ui \
|
||||||
@@ -103,7 +105,8 @@ FORMS += \
|
|||||||
androiddevicedialog.ui \
|
androiddevicedialog.ui \
|
||||||
androiddeployqtwidget.ui \
|
androiddeployqtwidget.ui \
|
||||||
androidbuildapkwidget.ui \
|
androidbuildapkwidget.ui \
|
||||||
androidrunconfigurationwidget.ui
|
androidrunconfigurationwidget.ui \
|
||||||
|
adbcommandswidget.ui
|
||||||
|
|
||||||
RESOURCES = android.qrc
|
RESOURCES = android.qrc
|
||||||
|
|
||||||
|
@@ -18,8 +18,11 @@ Project {
|
|||||||
|
|
||||||
files: [
|
files: [
|
||||||
"android_global.h",
|
"android_global.h",
|
||||||
"addnewavddialog.ui",
|
|
||||||
"android.qrc",
|
"android.qrc",
|
||||||
|
"adbcommandswidget.cpp",
|
||||||
|
"adbcommandswidget.h",
|
||||||
|
"adbcommandswidget.ui",
|
||||||
|
"addnewavddialog.ui",
|
||||||
"androidanalyzesupport.cpp",
|
"androidanalyzesupport.cpp",
|
||||||
"androidanalyzesupport.h",
|
"androidanalyzesupport.h",
|
||||||
"androidavdmanager.cpp",
|
"androidavdmanager.cpp",
|
||||||
|
@@ -40,7 +40,10 @@ using namespace ProjectExplorer;
|
|||||||
|
|
||||||
namespace Android {
|
namespace Android {
|
||||||
using namespace Internal;
|
using namespace Internal;
|
||||||
|
|
||||||
const char amStartArgsKey[] = "Android.AmStartArgsKey";
|
const char amStartArgsKey[] = "Android.AmStartArgsKey";
|
||||||
|
const char preStartShellCmdsKey[] = "Android.PreStartShellCmdListKey";
|
||||||
|
const char postFinishShellCmdsKey[] = "Android.PostFinishShellCmdListKey";
|
||||||
|
|
||||||
AndroidRunConfiguration::AndroidRunConfiguration(Target *parent, Core::Id id)
|
AndroidRunConfiguration::AndroidRunConfiguration(Target *parent, Core::Id id)
|
||||||
: RunConfiguration(parent, id)
|
: RunConfiguration(parent, id)
|
||||||
@@ -52,6 +55,16 @@ AndroidRunConfiguration::AndroidRunConfiguration(Target *parent, AndroidRunConfi
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AndroidRunConfiguration::setPreStartShellCommands(const QStringList &cmdList)
|
||||||
|
{
|
||||||
|
m_preStartShellCommands = cmdList;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidRunConfiguration::setPostFinishShellCommands(const QStringList &cmdList)
|
||||||
|
{
|
||||||
|
m_postFinishShellCommands = cmdList;
|
||||||
|
}
|
||||||
|
|
||||||
void AndroidRunConfiguration::setAmStartExtraArgs(const QStringList &args)
|
void AndroidRunConfiguration::setAmStartExtraArgs(const QStringList &args)
|
||||||
{
|
{
|
||||||
m_amStartExtraArgs = args;
|
m_amStartExtraArgs = args;
|
||||||
@@ -61,8 +74,14 @@ QWidget *AndroidRunConfiguration::createConfigurationWidget()
|
|||||||
{
|
{
|
||||||
auto configWidget = new AndroidRunConfigurationWidget();
|
auto configWidget = new AndroidRunConfigurationWidget();
|
||||||
configWidget->setAmStartArgs(m_amStartExtraArgs);
|
configWidget->setAmStartArgs(m_amStartExtraArgs);
|
||||||
|
configWidget->setPreStartShellCommands(m_preStartShellCommands);
|
||||||
|
configWidget->setPostFinishShellCommands(m_postFinishShellCommands);
|
||||||
connect(configWidget, &AndroidRunConfigurationWidget::amStartArgsChanged,
|
connect(configWidget, &AndroidRunConfigurationWidget::amStartArgsChanged,
|
||||||
this, &AndroidRunConfiguration::setAmStartExtraArgs);
|
this, &AndroidRunConfiguration::setAmStartExtraArgs);
|
||||||
|
connect(configWidget, &AndroidRunConfigurationWidget::preStartCmdsChanged,
|
||||||
|
this, &AndroidRunConfiguration::setPreStartShellCommands);
|
||||||
|
connect(configWidget, &AndroidRunConfigurationWidget::postFinishCmdsChanged,
|
||||||
|
this, &AndroidRunConfiguration::setPostFinishShellCommands);
|
||||||
return configWidget;
|
return configWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +92,8 @@ Utils::OutputFormatter *AndroidRunConfiguration::createOutputFormatter() const
|
|||||||
|
|
||||||
bool AndroidRunConfiguration::fromMap(const QVariantMap &map)
|
bool AndroidRunConfiguration::fromMap(const QVariantMap &map)
|
||||||
{
|
{
|
||||||
|
m_preStartShellCommands = map.value(preStartShellCmdsKey).toStringList();
|
||||||
|
m_postFinishShellCommands = map.value(postFinishShellCmdsKey).toStringList();
|
||||||
m_amStartExtraArgs = map.value(amStartArgsKey).toStringList();
|
m_amStartExtraArgs = map.value(amStartArgsKey).toStringList();
|
||||||
return RunConfiguration::fromMap(map);
|
return RunConfiguration::fromMap(map);
|
||||||
}
|
}
|
||||||
@@ -80,6 +101,8 @@ bool AndroidRunConfiguration::fromMap(const QVariantMap &map)
|
|||||||
QVariantMap AndroidRunConfiguration::toMap() const
|
QVariantMap AndroidRunConfiguration::toMap() const
|
||||||
{
|
{
|
||||||
QVariantMap res = RunConfiguration::toMap();
|
QVariantMap res = RunConfiguration::toMap();
|
||||||
|
res[preStartShellCmdsKey] = m_preStartShellCommands;
|
||||||
|
res[postFinishShellCmdsKey] = m_postFinishShellCommands;
|
||||||
res[amStartArgsKey] = m_amStartExtraArgs;
|
res[amStartArgsKey] = m_amStartExtraArgs;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -88,4 +111,15 @@ const QStringList &AndroidRunConfiguration::amStartExtraArgs() const
|
|||||||
{
|
{
|
||||||
return m_amStartExtraArgs;
|
return m_amStartExtraArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QStringList &AndroidRunConfiguration::preStartShellCommands() const
|
||||||
|
{
|
||||||
|
return m_preStartShellCommands;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QStringList &AndroidRunConfiguration::postFinishShellCommands() const
|
||||||
|
{
|
||||||
|
return m_postFinishShellCommands;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Android
|
} // namespace Android
|
||||||
|
@@ -48,15 +48,21 @@ public:
|
|||||||
QVariantMap toMap() const override;
|
QVariantMap toMap() const override;
|
||||||
|
|
||||||
const QStringList &amStartExtraArgs() const;
|
const QStringList &amStartExtraArgs() const;
|
||||||
|
const QStringList &preStartShellCommands() const;
|
||||||
|
const QStringList &postFinishShellCommands() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AndroidRunConfiguration(ProjectExplorer::Target *parent, AndroidRunConfiguration *source);
|
AndroidRunConfiguration(ProjectExplorer::Target *parent, AndroidRunConfiguration *source);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void setPreStartShellCommands(const QStringList &cmdList);
|
||||||
|
void setPostFinishShellCommands(const QStringList &cmdList);
|
||||||
void setAmStartExtraArgs(const QStringList &args);
|
void setAmStartExtraArgs(const QStringList &args);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QStringList m_amStartExtraArgs;
|
QStringList m_amStartExtraArgs;
|
||||||
|
QStringList m_preStartShellCommands;
|
||||||
|
QStringList m_postFinishShellCommands;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Android
|
} // namespace Android
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include "androidrunconfigurationwidget.h"
|
#include "androidrunconfigurationwidget.h"
|
||||||
|
#include "adbcommandswidget.h"
|
||||||
#include "ui_androidrunconfigurationwidget.h"
|
#include "ui_androidrunconfigurationwidget.h"
|
||||||
|
|
||||||
#include "utils/utilsicons.h"
|
#include "utils/utilsicons.h"
|
||||||
@@ -39,6 +40,26 @@ AndroidRunConfigurationWidget::AndroidRunConfigurationWidget(QWidget *parent):
|
|||||||
m_ui->setupUi(detailsWidget);
|
m_ui->setupUi(detailsWidget);
|
||||||
m_ui->m_warningIconLabel->setPixmap(Utils::Icons::WARNING.pixmap());
|
m_ui->m_warningIconLabel->setPixmap(Utils::Icons::WARNING.pixmap());
|
||||||
|
|
||||||
|
m_preStartCmdsWidget = new AdbCommandsWidget(detailsWidget);
|
||||||
|
connect(m_preStartCmdsWidget, &AdbCommandsWidget::commandsChanged, [this]() {
|
||||||
|
emit preStartCmdsChanged(m_preStartCmdsWidget->commandsList());
|
||||||
|
});
|
||||||
|
m_preStartCmdsWidget->setTitleText(tr("Shell commands to run on Android device before"
|
||||||
|
" application launch."));
|
||||||
|
|
||||||
|
m_postEndCmdsWidget = new AdbCommandsWidget(detailsWidget);
|
||||||
|
connect(m_postEndCmdsWidget, &AdbCommandsWidget::commandsChanged, [this]() {
|
||||||
|
emit postFinishCmdsChanged(m_postEndCmdsWidget->commandsList());
|
||||||
|
});
|
||||||
|
m_postEndCmdsWidget->setTitleText(tr("Shell commands to run on Android device after application"
|
||||||
|
" quits."));
|
||||||
|
|
||||||
|
auto mainLayout = static_cast<QGridLayout*>(detailsWidget->layout());
|
||||||
|
mainLayout->addWidget(m_preStartCmdsWidget->widget(), mainLayout->rowCount(),
|
||||||
|
0, mainLayout->columnCount() - 1, 0);
|
||||||
|
mainLayout->addWidget(m_postEndCmdsWidget->widget(), mainLayout->rowCount(),
|
||||||
|
0, mainLayout->columnCount() - 1, 0);
|
||||||
|
|
||||||
setWidget(detailsWidget);
|
setWidget(detailsWidget);
|
||||||
setSummaryText(tr("Android run settings"));
|
setSummaryText(tr("Android run settings"));
|
||||||
|
|
||||||
@@ -54,8 +75,17 @@ AndroidRunConfigurationWidget::~AndroidRunConfigurationWidget()
|
|||||||
|
|
||||||
void AndroidRunConfigurationWidget::setAmStartArgs(const QStringList &args)
|
void AndroidRunConfigurationWidget::setAmStartArgs(const QStringList &args)
|
||||||
{
|
{
|
||||||
if (m_ui->m_amStartArgsEdit && !args.isEmpty())
|
m_ui->m_amStartArgsEdit->setText(Utils::QtcProcess::joinArgs(args, Utils::OsTypeLinux));
|
||||||
m_ui->m_amStartArgsEdit->setText(Utils::QtcProcess::joinArgs(args, Utils::OsTypeLinux));
|
}
|
||||||
|
|
||||||
|
void AndroidRunConfigurationWidget::setPreStartShellCommands(const QStringList &cmdList)
|
||||||
|
{
|
||||||
|
m_preStartCmdsWidget->setCommandList(cmdList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidRunConfigurationWidget::setPostFinishShellCommands(const QStringList &cmdList)
|
||||||
|
{
|
||||||
|
m_postEndCmdsWidget->setCommandList(cmdList);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -29,10 +29,14 @@
|
|||||||
#include "projectexplorer/runconfiguration.h"
|
#include "projectexplorer/runconfiguration.h"
|
||||||
#include "utils/detailswidget.h"
|
#include "utils/detailswidget.h"
|
||||||
|
|
||||||
|
#include <QStringListModel>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace Android {
|
namespace Android {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
class AdbCommandsWidget;
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class AndroidRunConfigurationWidget;
|
class AndroidRunConfigurationWidget;
|
||||||
}
|
}
|
||||||
@@ -45,12 +49,22 @@ public:
|
|||||||
~AndroidRunConfigurationWidget();
|
~AndroidRunConfigurationWidget();
|
||||||
|
|
||||||
void setAmStartArgs(const QStringList &args);
|
void setAmStartArgs(const QStringList &args);
|
||||||
|
void setPreStartShellCommands(const QStringList &cmdList);
|
||||||
|
void setPostFinishShellCommands(const QStringList &cmdList);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void amStartArgsChanged(QStringList args);
|
void amStartArgsChanged(QStringList args);
|
||||||
|
void preStartCmdsChanged(const QStringList &cmdList);
|
||||||
|
void postFinishCmdsChanged(const QStringList &cmdList);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void addPreStartCommand(const QString &command);
|
||||||
|
void addPostFinishCommand(const QString &command);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Ui::AndroidRunConfigurationWidget> m_ui;
|
std::unique_ptr<Ui::AndroidRunConfigurationWidget> m_ui;
|
||||||
|
AdbCommandsWidget *m_preStartCmdsWidget = nullptr;
|
||||||
|
AdbCommandsWidget *m_postEndCmdsWidget = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -6,25 +6,31 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>625</width>
|
<width>731</width>
|
||||||
<height>73</height>
|
<height>119</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="2">
|
<property name="spacing">
|
||||||
<widget class="QLineEdit" name="m_amStartArgsEdit"/>
|
<number>-1</number>
|
||||||
</item>
|
</property>
|
||||||
<item row="1" column="2">
|
<item row="1" column="0" colspan="2">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Conflicting "am start" options might result in the app startup failure.</string>
|
<string>Activity manager start options:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QLabel" name="m_warningIconLabel">
|
<widget class="QLabel" name="m_warningIconLabel">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||||
@@ -37,7 +43,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="2" column="0">
|
||||||
<spacer name="horizontalSpacer">
|
<spacer name="horizontalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
@@ -53,13 +59,32 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0" colspan="2">
|
<item row="3" column="0" colspan="3">
|
||||||
<widget class="QLabel" name="label">
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>12</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Activity manager start options:</string>
|
<string>Conflicting "am start" options might result in the app startup failure.</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QLineEdit" name="m_amStartArgsEdit"/>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@@ -37,8 +37,8 @@ struct ANDROID_EXPORT AndroidRunnable
|
|||||||
QString intentName;
|
QString intentName;
|
||||||
QStringList amStartExtraArgs;
|
QStringList amStartExtraArgs;
|
||||||
Utils::Environment environment;
|
Utils::Environment environment;
|
||||||
QVector<QStringList> beforeStartADBCommands;
|
QStringList beforeStartAdbCommands;
|
||||||
QVector<QStringList> afterFinishADBCommands;
|
QStringList afterFinishAdbCommands;
|
||||||
QString deviceSerialNumber;
|
QString deviceSerialNumber;
|
||||||
|
|
||||||
QString displayName() const { return packageName; }
|
QString displayName() const { return packageName; }
|
||||||
@@ -51,8 +51,8 @@ inline bool operator==(const AndroidRunnable &r1, const AndroidRunnable &r2)
|
|||||||
&& r1.intentName == r2.intentName
|
&& r1.intentName == r2.intentName
|
||||||
&& r1.amStartExtraArgs == r2.amStartExtraArgs
|
&& r1.amStartExtraArgs == r2.amStartExtraArgs
|
||||||
&& r1.environment == r2.environment
|
&& r1.environment == r2.environment
|
||||||
&& r1.beforeStartADBCommands == r2.beforeStartADBCommands
|
&& r1.beforeStartAdbCommands == r2.beforeStartAdbCommands
|
||||||
&& r1.afterFinishADBCommands == r2.afterFinishADBCommands
|
&& r1.afterFinishAdbCommands == r2.afterFinishAdbCommands
|
||||||
&& r1.deviceSerialNumber == r2.deviceSerialNumber;
|
&& r1.deviceSerialNumber == r2.deviceSerialNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -214,14 +214,13 @@ class AndroidRunnerWorker : public QObject
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AndroidRunnerWorker(RunControl *runControl, const QString &packageName,
|
AndroidRunnerWorker(RunControl *runControl, const AndroidRunnable &runnable);
|
||||||
const QStringList &selector);
|
|
||||||
~AndroidRunnerWorker();
|
~AndroidRunnerWorker();
|
||||||
|
|
||||||
void asyncStart(const AndroidRunnable &runnable);
|
void asyncStart();
|
||||||
void asyncStop(const AndroidRunnable &runnable);
|
void asyncStop();
|
||||||
|
|
||||||
void setAdbParameters(const QString &packageName, const QStringList &selector);
|
void setAndroidRunnable(const AndroidRunnable &runnable);
|
||||||
void handleRemoteDebuggerRunning();
|
void handleRemoteDebuggerRunning();
|
||||||
|
|
||||||
Utils::Port localGdbServerPort() const { return m_localGdbServerPort; }
|
Utils::Port localGdbServerPort() const { return m_localGdbServerPort; }
|
||||||
@@ -238,7 +237,7 @@ private:
|
|||||||
void logcatReadStandardError();
|
void logcatReadStandardError();
|
||||||
void logcatReadStandardOutput();
|
void logcatReadStandardOutput();
|
||||||
void adbKill(qint64 pid);
|
void adbKill(qint64 pid);
|
||||||
QStringList selector() const { return m_selector; }
|
QStringList selector() const;
|
||||||
void forceStop();
|
void forceStop();
|
||||||
void findPs();
|
void findPs();
|
||||||
void logcatProcess(const QByteArray &text, QByteArray &buffer, bool onlyError);
|
void logcatProcess(const QByteArray &text, QByteArray &buffer, bool onlyError);
|
||||||
@@ -264,22 +263,19 @@ private:
|
|||||||
QString m_gdbserverPath;
|
QString m_gdbserverPath;
|
||||||
QString m_gdbserverSocket;
|
QString m_gdbserverSocket;
|
||||||
QString m_adb;
|
QString m_adb;
|
||||||
QStringList m_selector;
|
|
||||||
QRegExp m_logCatRegExp;
|
QRegExp m_logCatRegExp;
|
||||||
DebugHandShakeType m_handShakeMethod = SocketHandShake;
|
DebugHandShakeType m_handShakeMethod = SocketHandShake;
|
||||||
bool m_customPort = false;
|
bool m_customPort = false;
|
||||||
|
|
||||||
QString m_packageName;
|
AndroidRunnable m_androidRunnable;
|
||||||
int m_socketHandShakePort = MIN_SOCKET_HANDSHAKE_PORT;
|
int m_socketHandShakePort = MIN_SOCKET_HANDSHAKE_PORT;
|
||||||
};
|
};
|
||||||
|
|
||||||
AndroidRunnerWorker::AndroidRunnerWorker(RunControl *runControl, const QString &packageName,
|
AndroidRunnerWorker::AndroidRunnerWorker(RunControl *runControl, const AndroidRunnable &runnable)
|
||||||
const QStringList &selector)
|
|
||||||
: m_adbLogcatProcess(nullptr, deleter)
|
: m_adbLogcatProcess(nullptr, deleter)
|
||||||
, m_psIsAlive(nullptr, deleter)
|
, m_psIsAlive(nullptr, deleter)
|
||||||
, m_selector(selector)
|
|
||||||
, m_logCatRegExp(regExpLogcat)
|
, m_logCatRegExp(regExpLogcat)
|
||||||
, m_packageName(packageName)
|
, m_androidRunnable(runnable)
|
||||||
{
|
{
|
||||||
auto runConfig = runControl->runConfiguration();
|
auto runConfig = runControl->runConfiguration();
|
||||||
auto aspect = runConfig->extraAspect<Debugger::DebuggerRunConfigurationAspect>();
|
auto aspect = runConfig->extraAspect<Debugger::DebuggerRunConfigurationAspect>();
|
||||||
@@ -307,9 +303,9 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunControl *runControl, const QString &
|
|||||||
}
|
}
|
||||||
m_adb = AndroidConfigurations::currentConfig().adbToolPath().toString();
|
m_adb = AndroidConfigurations::currentConfig().adbToolPath().toString();
|
||||||
|
|
||||||
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(
|
const QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(
|
||||||
runConfig->target()->kit());
|
runConfig->target()->kit());
|
||||||
@@ -347,20 +343,20 @@ AndroidRunnerWorker::~AndroidRunnerWorker()
|
|||||||
|
|
||||||
void AndroidRunnerWorker::forceStop()
|
void AndroidRunnerWorker::forceStop()
|
||||||
{
|
{
|
||||||
runAdb({"shell", "am", "force-stop", m_packageName}, nullptr, 30);
|
runAdb({"shell", "am", "force-stop", m_androidRunnable.packageName}, nullptr, 30);
|
||||||
|
|
||||||
// try killing it via kill -9
|
// try killing it via kill -9
|
||||||
const QByteArray out = Utils::SynchronousProcess()
|
const QByteArray out = Utils::SynchronousProcess()
|
||||||
.runBlocking(m_adb, selector() << QStringLiteral("shell") << pidScript)
|
.runBlocking(m_adb, selector() << QStringLiteral("shell") << pidScript)
|
||||||
.allRawOutput();
|
.allRawOutput();
|
||||||
|
|
||||||
qint64 pid = extractPID(out.simplified(), m_packageName);
|
qint64 pid = extractPID(out.simplified(), m_androidRunnable.packageName);
|
||||||
if (pid != -1) {
|
if (pid != -1) {
|
||||||
adbKill(pid);
|
adbKill(pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidRunnerWorker::asyncStart(const AndroidRunnable &runnable)
|
void AndroidRunnerWorker::asyncStart()
|
||||||
{
|
{
|
||||||
forceStop();
|
forceStop();
|
||||||
|
|
||||||
@@ -378,12 +374,12 @@ void AndroidRunnerWorker::asyncStart(const AndroidRunnable &runnable)
|
|||||||
if (m_useCppDebugger)
|
if (m_useCppDebugger)
|
||||||
runAdb({"shell", "rm", m_pongFile}); // Remove pong file.
|
runAdb({"shell", "rm", m_pongFile}); // Remove pong file.
|
||||||
|
|
||||||
for (const QStringList &entry: runnable.beforeStartADBCommands)
|
for (const QString &entry: m_androidRunnable.beforeStartAdbCommands)
|
||||||
runAdb(entry);
|
runAdb(entry.split(' ', QString::SkipEmptyParts));
|
||||||
|
|
||||||
QStringList args({"shell", "am", "start"});
|
QStringList args({"shell", "am", "start"});
|
||||||
args << runnable.amStartExtraArgs;
|
args << m_androidRunnable.amStartExtraArgs;
|
||||||
args << "-n" << runnable.intentName;
|
args << "-n" << m_androidRunnable.intentName;
|
||||||
|
|
||||||
if (m_useCppDebugger) {
|
if (m_useCppDebugger) {
|
||||||
if (!runAdb({"forward", "--remove", "tcp:" + m_localGdbServerPort.toString()})){
|
if (!runAdb({"forward", "--remove", "tcp:" + m_localGdbServerPort.toString()})){
|
||||||
@@ -395,7 +391,7 @@ void AndroidRunnerWorker::asyncStart(const AndroidRunnable &runnable)
|
|||||||
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;
|
||||||
@@ -499,7 +495,8 @@ void AndroidRunnerWorker::asyncStart(const AndroidRunnable &runnable)
|
|||||||
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();
|
||||||
@@ -512,7 +509,7 @@ void AndroidRunnerWorker::asyncStart(const AndroidRunnable &runnable)
|
|||||||
QTC_ASSERT(!m_adbLogcatProcess, /**/);
|
QTC_ASSERT(!m_adbLogcatProcess, /**/);
|
||||||
m_adbLogcatProcess = std::move(logcatProcess);
|
m_adbLogcatProcess = std::move(logcatProcess);
|
||||||
m_pidFinder = Utils::onResultReady(Utils::runAsync(&findProcessPID, m_adb, selector(),
|
m_pidFinder = Utils::onResultReady(Utils::runAsync(&findProcessPID, m_adb, selector(),
|
||||||
m_packageName),
|
m_androidRunnable.packageName),
|
||||||
bind(&AndroidRunnerWorker::onProcessIdChanged, this, _1));
|
bind(&AndroidRunnerWorker::onProcessIdChanged, this, _1));
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -543,7 +540,7 @@ bool AndroidRunnerWorker::runAdb(const QStringList &args, QString *exitMessage,
|
|||||||
{
|
{
|
||||||
Utils::SynchronousProcess adb;
|
Utils::SynchronousProcess adb;
|
||||||
adb.setTimeoutS(timeoutS);
|
adb.setTimeoutS(timeoutS);
|
||||||
Utils::SynchronousProcessResponse response = adb.run(m_adb, m_selector + args);
|
Utils::SynchronousProcessResponse response = adb.run(m_adb, selector() + args);
|
||||||
if (exitMessage)
|
if (exitMessage)
|
||||||
*exitMessage = response.exitMessage(m_adb, timeoutS);
|
*exitMessage = response.exitMessage(m_adb, timeoutS);
|
||||||
return response.result == Utils::SynchronousProcessResponse::Finished;
|
return response.result == Utils::SynchronousProcessResponse::Finished;
|
||||||
@@ -567,7 +564,7 @@ void AndroidRunnerWorker::handleRemoteDebuggerRunning()
|
|||||||
// emit remoteProcessStarted(m_localGdbServerPort, m_qmlPort);
|
// emit remoteProcessStarted(m_localGdbServerPort, m_qmlPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidRunnerWorker::asyncStop(const AndroidRunnable &runnable)
|
void AndroidRunnerWorker::asyncStop()
|
||||||
{
|
{
|
||||||
if (!m_pidFinder.isFinished())
|
if (!m_pidFinder.isFinished())
|
||||||
m_pidFinder.cancel();
|
m_pidFinder.cancel();
|
||||||
@@ -575,14 +572,11 @@ void AndroidRunnerWorker::asyncStop(const AndroidRunnable &runnable)
|
|||||||
if (m_processPID != -1) {
|
if (m_processPID != -1) {
|
||||||
forceStop();
|
forceStop();
|
||||||
}
|
}
|
||||||
for (const QStringList &entry: runnable.afterFinishADBCommands)
|
|
||||||
runAdb(entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidRunnerWorker::setAdbParameters(const QString &packageName, const QStringList &selector)
|
void AndroidRunnerWorker::setAndroidRunnable(const AndroidRunnable &runnable)
|
||||||
{
|
{
|
||||||
m_packageName = packageName;
|
m_androidRunnable = runnable;
|
||||||
m_selector = selector;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidRunnerWorker::logcatProcess(const QByteArray &text, QByteArray &buffer, bool onlyError)
|
void AndroidRunnerWorker::logcatProcess(const QByteArray &text, QByteArray &buffer, bool onlyError)
|
||||||
@@ -635,10 +629,14 @@ void AndroidRunnerWorker::onProcessIdChanged(qint64 pid)
|
|||||||
m_processPID = pid;
|
m_processPID = pid;
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
emit remoteProcessFinished(QLatin1String("\n\n") + tr("\"%1\" died.")
|
emit remoteProcessFinished(QLatin1String("\n\n") + tr("\"%1\" died.")
|
||||||
.arg(m_packageName));
|
.arg(m_androidRunnable.packageName));
|
||||||
// App died/killed. Reset log and monitor processes.
|
// App died/killed. Reset log and monitor processes.
|
||||||
m_adbLogcatProcess.reset();
|
m_adbLogcatProcess.reset();
|
||||||
m_psIsAlive.reset();
|
m_psIsAlive.reset();
|
||||||
|
|
||||||
|
// Run adb commands after application quit.
|
||||||
|
for (const QString &entry: m_androidRunnable.afterFinishAdbCommands)
|
||||||
|
runAdb(entry.split(' ', QString::SkipEmptyParts));
|
||||||
} else {
|
} else {
|
||||||
// In debugging cases this will be funneled to the engine to actually start
|
// In debugging cases this will be funneled to the engine to actually start
|
||||||
// and attach gdb. Afterwards this ends up in handleRemoteDebuggerRunning() below.
|
// and attach gdb. Afterwards this ends up in handleRemoteDebuggerRunning() below.
|
||||||
@@ -671,7 +669,12 @@ void AndroidRunnerWorker::logcatReadStandardOutput()
|
|||||||
void AndroidRunnerWorker::adbKill(qint64 pid)
|
void AndroidRunnerWorker::adbKill(qint64 pid)
|
||||||
{
|
{
|
||||||
runAdb({"shell", "kill", "-9", QString::number(pid)});
|
runAdb({"shell", "kill", "-9", QString::number(pid)});
|
||||||
runAdb({"shell", "run-as", m_packageName, "kill", "-9", QString::number(pid)});
|
runAdb({"shell", "run-as", m_androidRunnable.packageName, "kill", "-9", QString::number(pid)});
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList AndroidRunnerWorker::selector() const
|
||||||
|
{
|
||||||
|
return AndroidDeviceInfo::adbSelector(m_androidRunnable.deviceSerialNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidRunner::AndroidRunner(RunControl *runControl)
|
AndroidRunner::AndroidRunner(RunControl *runControl)
|
||||||
@@ -694,15 +697,19 @@ AndroidRunner::AndroidRunner(RunControl *runControl)
|
|||||||
|
|
||||||
auto androidRunConfig = qobject_cast<AndroidRunConfiguration *>(runControl->runConfiguration());
|
auto androidRunConfig = qobject_cast<AndroidRunConfiguration *>(runControl->runConfiguration());
|
||||||
m_androidRunnable.amStartExtraArgs = androidRunConfig->amStartExtraArgs();
|
m_androidRunnable.amStartExtraArgs = androidRunConfig->amStartExtraArgs();
|
||||||
|
for (QString shellCmd: androidRunConfig->preStartShellCommands())
|
||||||
|
m_androidRunnable.beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd));
|
||||||
|
|
||||||
m_worker.reset(new AndroidRunnerWorker(runControl, m_androidRunnable.packageName,
|
for (QString shellCmd: androidRunConfig->postFinishShellCommands())
|
||||||
AndroidDeviceInfo::adbSelector(m_androidRunnable.deviceSerialNumber)));
|
m_androidRunnable.afterFinishAdbCommands.append(QString("shell %1").arg(shellCmd));
|
||||||
|
|
||||||
|
m_worker.reset(new AndroidRunnerWorker(runControl, m_androidRunnable));
|
||||||
m_worker->moveToThread(&m_thread);
|
m_worker->moveToThread(&m_thread);
|
||||||
|
|
||||||
connect(this, &AndroidRunner::asyncStart, m_worker.data(), &AndroidRunnerWorker::asyncStart);
|
connect(this, &AndroidRunner::asyncStart, m_worker.data(), &AndroidRunnerWorker::asyncStart);
|
||||||
connect(this, &AndroidRunner::asyncStop, m_worker.data(), &AndroidRunnerWorker::asyncStop);
|
connect(this, &AndroidRunner::asyncStop, m_worker.data(), &AndroidRunnerWorker::asyncStop);
|
||||||
connect(this, &AndroidRunner::adbParametersChanged,
|
connect(this, &AndroidRunner::androidRunnableChanged,
|
||||||
m_worker.data(), &AndroidRunnerWorker::setAdbParameters);
|
m_worker.data(), &AndroidRunnerWorker::setAndroidRunnable);
|
||||||
connect(this, &AndroidRunner::remoteDebuggerRunning,
|
connect(this, &AndroidRunner::remoteDebuggerRunning,
|
||||||
m_worker.data(), &AndroidRunnerWorker::handleRemoteDebuggerRunning);
|
m_worker.data(), &AndroidRunnerWorker::handleRemoteDebuggerRunning);
|
||||||
|
|
||||||
@@ -738,7 +745,7 @@ void AndroidRunner::start()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit asyncStart(m_androidRunnable);
|
emit asyncStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidRunner::stop()
|
void AndroidRunner::stop()
|
||||||
@@ -750,7 +757,7 @@ void AndroidRunner::stop()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit asyncStop(m_androidRunnable);
|
emit asyncStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidRunner::qmlServerPortReady(Port port)
|
void AndroidRunner::qmlServerPortReady(Port port)
|
||||||
@@ -797,8 +804,7 @@ void AndroidRunner::setRunnable(const AndroidRunnable &runnable)
|
|||||||
{
|
{
|
||||||
if (runnable != m_androidRunnable) {
|
if (runnable != m_androidRunnable) {
|
||||||
m_androidRunnable = runnable;
|
m_androidRunnable = runnable;
|
||||||
emit adbParametersChanged(runnable.packageName,
|
emit androidRunnableChanged(m_androidRunnable);
|
||||||
AndroidDeviceInfo::adbSelector(runnable.deviceSerialNumber));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -816,8 +822,7 @@ void AndroidRunner::launchAVD()
|
|||||||
AndroidConfigurations::None);
|
AndroidConfigurations::None);
|
||||||
AndroidManager::setDeviceSerialNumber(m_target, info.serialNumber);
|
AndroidManager::setDeviceSerialNumber(m_target, info.serialNumber);
|
||||||
m_androidRunnable.deviceSerialNumber = info.serialNumber;
|
m_androidRunnable.deviceSerialNumber = info.serialNumber;
|
||||||
emit adbParametersChanged(m_androidRunnable.packageName,
|
emit androidRunnableChanged(m_androidRunnable);
|
||||||
AndroidDeviceInfo::adbSelector(info.serialNumber));
|
|
||||||
if (info.isValid()) {
|
if (info.isValid()) {
|
||||||
AndroidAvdManager avdManager;
|
AndroidAvdManager avdManager;
|
||||||
if (avdManager.findAvd(info.avdname).isEmpty()) {
|
if (avdManager.findAvd(info.avdname).isEmpty()) {
|
||||||
@@ -840,7 +845,7 @@ void AndroidRunner::checkAVD()
|
|||||||
if (avdManager.isAvdBooted(serialNumber)) {
|
if (avdManager.isAvdBooted(serialNumber)) {
|
||||||
m_checkAVDTimer.stop();
|
m_checkAVDTimer.stop();
|
||||||
AndroidManager::setDeviceSerialNumber(m_target, serialNumber);
|
AndroidManager::setDeviceSerialNumber(m_target, serialNumber);
|
||||||
emit asyncStart(m_androidRunnable);
|
emit asyncStart();
|
||||||
} else if (!config.isConnected(serialNumber)) {
|
} else if (!config.isConnected(serialNumber)) {
|
||||||
// device was disconnected
|
// device was disconnected
|
||||||
m_checkAVDTimer.stop();
|
m_checkAVDTimer.stop();
|
||||||
|
@@ -64,12 +64,11 @@ public:
|
|||||||
void stop() override;
|
void stop() override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void asyncStart(const AndroidRunnable &runnable);
|
void asyncStart();
|
||||||
void asyncStop(const AndroidRunnable &runnable);
|
void asyncStop();
|
||||||
void remoteDebuggerRunning();
|
void remoteDebuggerRunning();
|
||||||
void qmlServerReady(const QUrl &serverUrl);
|
void qmlServerReady(const QUrl &serverUrl);
|
||||||
|
void androidRunnableChanged(const AndroidRunnable &runnable);
|
||||||
void adbParametersChanged(const QString &packageName, const QStringList &selector);
|
|
||||||
void avdDetected();
|
void avdDetected();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Reference in New Issue
Block a user