forked from qt-creator/qt-creator
		
	Note, that we don't know the names of the started avds, so we look for a avd that has the same abi and apiLevel. Task-number: QTCREATORBUG-10411 Change-Id: I5f6ff3ee0dddcf2bb8fca981ccedf437e32da677 Reviewed-by: BogDan Vatra <bogdan@kde.org>
		
			
				
	
	
		
			503 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			503 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/**************************************************************************
 | 
						|
**
 | 
						|
** Copyright (c) 2013 BogDan Vatra <bog_dan_ro@yahoo.com>
 | 
						|
** Contact: http://www.qt-project.org/legal
 | 
						|
**
 | 
						|
** 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 Digia.  For licensing terms and
 | 
						|
** conditions see http://qt.digia.com/licensing.  For further information
 | 
						|
** use the contact form at http://qt.digia.com/contact-us.
 | 
						|
**
 | 
						|
** GNU Lesser General Public License Usage
 | 
						|
** Alternatively, this file may be used under the terms of the GNU Lesser
 | 
						|
** General Public License version 2.1 as published by the Free Software
 | 
						|
** Foundation and appearing in the file LICENSE.LGPL included in the
 | 
						|
** packaging of this file.  Please review the following information to
 | 
						|
** ensure the GNU Lesser General Public License version 2.1 requirements
 | 
						|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 | 
						|
**
 | 
						|
** In addition, as a special exception, Digia gives you certain additional
 | 
						|
** rights.  These rights are described in the Digia Qt LGPL Exception
 | 
						|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 | 
						|
**
 | 
						|
****************************************************************************/
 | 
						|
 | 
						|
#include "androiddeploystep.h"
 | 
						|
 | 
						|
#include "androidconstants.h"
 | 
						|
#include "androiddeploystepwidget.h"
 | 
						|
#include "androidglobal.h"
 | 
						|
#include "androidpackagecreationstep.h"
 | 
						|
#include "androidrunconfiguration.h"
 | 
						|
#include "androidmanager.h"
 | 
						|
#include "androidtoolchain.h"
 | 
						|
#include "androiddevicedialog.h"
 | 
						|
 | 
						|
#include <coreplugin/messagemanager.h>
 | 
						|
#include <projectexplorer/buildconfiguration.h>
 | 
						|
#include <projectexplorer/deployconfiguration.h>
 | 
						|
#include <projectexplorer/projectexplorerconstants.h>
 | 
						|
#include <projectexplorer/buildsteplist.h>
 | 
						|
#include <projectexplorer/target.h>
 | 
						|
#include <qt4projectmanager/qmakebuildconfiguration.h>
 | 
						|
#include <qt4projectmanager/qmakeproject.h>
 | 
						|
#include <qt4projectmanager/qmakenodes.h>
 | 
						|
 | 
						|
#include <qtsupport/qtkitinformation.h>
 | 
						|
 | 
						|
#include <QDir>
 | 
						|
 | 
						|
#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
 | 
						|
 | 
						|
using namespace Core;
 | 
						|
using namespace ProjectExplorer;
 | 
						|
using namespace QmakeProjectManager;
 | 
						|
 | 
						|
namespace Android {
 | 
						|
namespace Internal {
 | 
						|
 | 
						|
static const char USE_LOCAL_QT_KEY[] = "Qt4ProjectManager.AndroidDeployStep.UseLocalQtLibs";
 | 
						|
static const char DEPLOY_ACTION_KEY[] = "Qt4ProjectManager.AndroidDeployStep.DeployAction";
 | 
						|
 | 
						|
const Id AndroidDeployStep::Id("Qt4ProjectManager.AndroidDeployStep");
 | 
						|
 | 
						|
AndroidDeployStep::AndroidDeployStep(ProjectExplorer::BuildStepList *parent)
 | 
						|
    : BuildStep(parent, Id)
 | 
						|
{
 | 
						|
    ctor();
 | 
						|
}
 | 
						|
 | 
						|
AndroidDeployStep::AndroidDeployStep(ProjectExplorer::BuildStepList *parent,
 | 
						|
    AndroidDeployStep *other)
 | 
						|
    : BuildStep(parent, other)
 | 
						|
{
 | 
						|
    ctor();
 | 
						|
}
 | 
						|
 | 
						|
AndroidDeployStep::~AndroidDeployStep() { }
 | 
						|
 | 
						|
void AndroidDeployStep::ctor()
 | 
						|
{
 | 
						|
    //: AndroidDeployStep default display name
 | 
						|
    setDefaultDisplayName(tr("Deploy to Android device"));
 | 
						|
    m_deployAction = NoDeploy;
 | 
						|
 | 
						|
    QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target()->kit());
 | 
						|
    m_bundleQtAvailable = qt && qt->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0);
 | 
						|
    if (m_bundleQtAvailable)
 | 
						|
        m_deployAction = BundleLibraries;
 | 
						|
 | 
						|
 | 
						|
    connect(ProjectExplorer::KitManager::instance(), SIGNAL(kitUpdated(ProjectExplorer::Kit*)),
 | 
						|
            this, SLOT(kitUpdated(ProjectExplorer::Kit*)));
 | 
						|
}
 | 
						|
 | 
						|
bool AndroidDeployStep::init()
 | 
						|
{
 | 
						|
    m_packageName = AndroidManager::packageName(target());
 | 
						|
    m_deviceAPILevel = AndroidManager::minimumSDK(target());
 | 
						|
    m_targetArch = AndroidManager::targetArch(target());
 | 
						|
 | 
						|
    AndroidDeviceInfo info = AndroidConfigurations::instance().showDeviceDialog(project(), m_deviceAPILevel, m_targetArch);
 | 
						|
    if (info.serialNumber.isEmpty()) // aborted
 | 
						|
        return false;
 | 
						|
 | 
						|
    m_deviceAPILevel = info.sdk;
 | 
						|
    m_deviceSerialNumber = info.serialNumber;
 | 
						|
 | 
						|
    if (info.type == AndroidDeviceInfo::Emulator)
 | 
						|
        m_avdName = m_deviceSerialNumber;
 | 
						|
 | 
						|
    QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
 | 
						|
    if (!version)
 | 
						|
        return false;
 | 
						|
 | 
						|
    const Qt4BuildConfiguration *bc = static_cast<Qt4BuildConfiguration *>(target()->activeBuildConfiguration());
 | 
						|
    if (!bc)
 | 
						|
        return false;
 | 
						|
 | 
						|
    m_signPackage = false;
 | 
						|
    // find AndroidPackageCreationStep
 | 
						|
    foreach (BuildStep *step, target()->activeDeployConfiguration()->stepList()->steps()) {
 | 
						|
        if (AndroidPackageCreationStep *apcs = qobject_cast<AndroidPackageCreationStep *>(step)) {
 | 
						|
            m_signPackage = apcs->signPackage();
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    m_qtVersionSourcePath = version->qmakeProperty("QT_INSTALL_PREFIX");
 | 
						|
    m_androidDirPath = AndroidManager::dirPath(target());
 | 
						|
    m_apkPathDebug = AndroidManager::apkPath(target(), AndroidManager::DebugBuild).toString();
 | 
						|
    m_apkPathRelease = AndroidManager::apkPath(target(), AndroidManager::ReleaseBuildSigned).toString();
 | 
						|
    m_buildDirectory = static_cast<Qt4Project *>(target()->project())->rootQt4ProjectNode()->buildDir();
 | 
						|
    m_runDeployAction = m_deployAction;
 | 
						|
    ToolChain *tc = ToolChainKitInformation::toolChain(target()->kit());
 | 
						|
    if (!tc || tc->type() != QLatin1String(Constants::ANDROID_TOOLCHAIN_TYPE)) {
 | 
						|
        raiseError(tr("No Android toolchain selected."));
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    m_ndkToolChainVersion = static_cast<AndroidToolChain *>(tc)->ndkToolChainVersion();
 | 
						|
 | 
						|
    QString arch = static_cast<Qt4Project *>(project())->rootQt4ProjectNode()->singleVariableValue(QmakeProjectManager::AndroidArchVar);
 | 
						|
    if (!arch.isEmpty())
 | 
						|
        m_libgnustl = AndroidManager::libGnuStl(arch, m_ndkToolChainVersion);
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
void AndroidDeployStep::run(QFutureInterface<bool> &fi)
 | 
						|
{
 | 
						|
    fi.reportResult(deployPackage());
 | 
						|
}
 | 
						|
 | 
						|
BuildStepConfigWidget *AndroidDeployStep::createConfigWidget()
 | 
						|
{
 | 
						|
    return new AndroidDeployStepWidget(this);
 | 
						|
}
 | 
						|
 | 
						|
AndroidDeployStep::AndroidDeployAction AndroidDeployStep::deployAction()
 | 
						|
{
 | 
						|
    return m_deployAction;
 | 
						|
}
 | 
						|
 | 
						|
bool AndroidDeployStep::fromMap(const QVariantMap &map)
 | 
						|
{
 | 
						|
    m_deployAction = AndroidDeployAction(map.value(QLatin1String(DEPLOY_ACTION_KEY), NoDeploy).toInt());
 | 
						|
    QVariant useLocalQt = map.value(QLatin1String(USE_LOCAL_QT_KEY));
 | 
						|
    if (useLocalQt.isValid()) { // old settings
 | 
						|
        if (useLocalQt.toBool() && m_deployAction == NoDeploy)
 | 
						|
            m_deployAction = BundleLibraries;
 | 
						|
    }
 | 
						|
 | 
						|
    if (m_deployAction == InstallQASI)
 | 
						|
        m_deployAction = NoDeploy;
 | 
						|
    QtSupport::BaseQtVersion *qtVersion
 | 
						|
            = QtSupport::QtKitInformation::qtVersion(target()->kit());
 | 
						|
    if (m_deployAction == BundleLibraries)
 | 
						|
        if (!qtVersion || qtVersion->qtVersion() < QtSupport::QtVersionNumber(5, 0, 0))
 | 
						|
            m_deployAction = NoDeploy; // the kit changed to a non qt5 kit
 | 
						|
 | 
						|
    m_bundleQtAvailable = qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0);
 | 
						|
 | 
						|
    return ProjectExplorer::BuildStep::fromMap(map);
 | 
						|
}
 | 
						|
 | 
						|
QVariantMap AndroidDeployStep::toMap() const
 | 
						|
{
 | 
						|
    QVariantMap map = ProjectExplorer::BuildStep::toMap();
 | 
						|
    map.insert(QLatin1String(DEPLOY_ACTION_KEY), m_deployAction);
 | 
						|
    return map;
 | 
						|
}
 | 
						|
 | 
						|
void AndroidDeployStep::kitUpdated(Kit *kit)
 | 
						|
{
 | 
						|
    if (kit != target()->kit())
 | 
						|
        return;
 | 
						|
    QtSupport::BaseQtVersion *qtVersion
 | 
						|
            = QtSupport::QtKitInformation::qtVersion(target()->kit());
 | 
						|
 | 
						|
    bool newBundleQtAvailable = qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0);
 | 
						|
    if (m_bundleQtAvailable != newBundleQtAvailable) {
 | 
						|
        m_bundleQtAvailable = newBundleQtAvailable;
 | 
						|
 | 
						|
        if (!m_bundleQtAvailable && m_deployAction == BundleLibraries)
 | 
						|
            m_deployAction = NoDeploy; // the kit changed to a non qt5 kit
 | 
						|
 | 
						|
        emit deployOptionsChanged();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
bool AndroidDeployStep::bundleQtOptionAvailable()
 | 
						|
{
 | 
						|
    return m_bundleQtAvailable;
 | 
						|
}
 | 
						|
 | 
						|
void AndroidDeployStep::setDeployAction(AndroidDeployStep::AndroidDeployAction deploy)
 | 
						|
{
 | 
						|
    m_deployAction = deploy;
 | 
						|
 | 
						|
    AndroidManager::updateDeploymentSettings(target());
 | 
						|
}
 | 
						|
 | 
						|
bool AndroidDeployStep::runCommand(QProcess *buildProc,
 | 
						|
    const QString &program, const QStringList &arguments)
 | 
						|
{
 | 
						|
    writeOutput(tr("Package deploy: Running command '%1 %2'.").arg(program).arg(arguments.join(QLatin1String(" "))), BuildStep::MessageOutput);
 | 
						|
    buildProc->start(program, arguments);
 | 
						|
    if (!buildProc->waitForStarted()) {
 | 
						|
        writeOutput(tr("Packaging error: Could not start command '%1 %2'. Reason: %3")
 | 
						|
            .arg(program).arg(arguments.join(QLatin1String(" "))).arg(buildProc->errorString()), BuildStep::ErrorMessageOutput);
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    if (!buildProc->waitForFinished(2 * 60 * 1000)
 | 
						|
            || buildProc->error() != QProcess::UnknownError
 | 
						|
            || buildProc->exitCode() != 0) {
 | 
						|
        QString mainMessage = tr("Packaging Error: Command '%1 %2' failed.")
 | 
						|
                .arg(program).arg(arguments.join(QLatin1String(" ")));
 | 
						|
        if (buildProc->error() != QProcess::UnknownError)
 | 
						|
            mainMessage += tr(" Reason: %1").arg(buildProc->errorString());
 | 
						|
        else
 | 
						|
            mainMessage += tr("Exit code: %1").arg(buildProc->exitCode());
 | 
						|
        writeOutput(mainMessage, BuildStep::ErrorMessageOutput);
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
void AndroidDeployStep::handleBuildOutput()
 | 
						|
{
 | 
						|
    QProcess *const buildProc = qobject_cast<QProcess *>(sender());
 | 
						|
    if (!buildProc)
 | 
						|
        return;
 | 
						|
    emit addOutput(QString::fromLocal8Bit(buildProc->readAllStandardOutput())
 | 
						|
                   , BuildStep::NormalOutput);
 | 
						|
}
 | 
						|
 | 
						|
void AndroidDeployStep::handleBuildError()
 | 
						|
{
 | 
						|
    QProcess *const buildProc = qobject_cast<QProcess *>(sender());
 | 
						|
    if (!buildProc)
 | 
						|
        return;
 | 
						|
    emit addOutput(QString::fromLocal8Bit(buildProc->readAllStandardError())
 | 
						|
                   , BuildStep::ErrorOutput);
 | 
						|
}
 | 
						|
 | 
						|
QString AndroidDeployStep::deviceSerialNumber()
 | 
						|
{
 | 
						|
    return m_deviceSerialNumber;
 | 
						|
}
 | 
						|
 | 
						|
unsigned int AndroidDeployStep::remoteModificationTime(const QString &fullDestination, QHash<QString, unsigned int> *cache)
 | 
						|
{
 | 
						|
    QString destination = QFileInfo(fullDestination).absolutePath();
 | 
						|
    QProcess process;
 | 
						|
    QHash<QString, unsigned int>::const_iterator it = cache->find(fullDestination);
 | 
						|
    if (it != cache->constEnd())
 | 
						|
        return *it;
 | 
						|
    QStringList arguments = AndroidDeviceInfo::adbSelector(m_deviceSerialNumber);
 | 
						|
    arguments << QLatin1String("ls") << destination;
 | 
						|
    process.start(AndroidConfigurations::instance().adbToolPath().toString(), arguments);
 | 
						|
    process.waitForFinished(-1);
 | 
						|
    if (process.error() != QProcess::UnknownError
 | 
						|
            || process.exitCode() != 0)
 | 
						|
        return -1;
 | 
						|
    QByteArray output = process.readAll();
 | 
						|
    output.replace("\r\n", "\n");
 | 
						|
    QList<QByteArray> lines = output.split('\n');
 | 
						|
    foreach (const QByteArray &line, lines) {
 | 
						|
        // do some checks if we got what we expected..
 | 
						|
        if (line.count() < (3 * 8 + 3))
 | 
						|
            continue;
 | 
						|
        if (line.at(8) != ' '
 | 
						|
                || line.at(17) != ' '
 | 
						|
                || line.at(26) != ' ')
 | 
						|
            continue;
 | 
						|
        bool ok;
 | 
						|
        int time = line.mid(18, 8).toUInt(&ok, 16);
 | 
						|
        if (!ok)
 | 
						|
            continue;
 | 
						|
        QString fileName = QString::fromLocal8Bit(line.mid(27));
 | 
						|
        cache->insert(destination + QLatin1Char('/') + fileName, time);
 | 
						|
    }
 | 
						|
    it = cache->find(fullDestination);
 | 
						|
    if (it != cache->constEnd())
 | 
						|
        return *it;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
void AndroidDeployStep::collectFiles(QList<DeployItem> *deployList, const QString &localPath, const QString &remotePath,
 | 
						|
                  bool strip, const QStringList &filter)
 | 
						|
{
 | 
						|
    QDirIterator libsIt(localPath, filter, QDir::NoFilter, QDirIterator::Subdirectories);
 | 
						|
    int pos = localPath.size();
 | 
						|
    while (libsIt.hasNext()) {
 | 
						|
        libsIt.next();
 | 
						|
        const QString destFile(remotePath + libsIt.filePath().mid(pos));
 | 
						|
        if (!libsIt.fileInfo().isDir()) {
 | 
						|
            deployList->append(DeployItem(libsIt.filePath(),
 | 
						|
                                          libsIt.fileInfo().lastModified().toTime_t(),
 | 
						|
                                          destFile, strip));
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void AndroidDeployStep::fetchRemoteModificationTimes(QList<DeployItem> *deployList)
 | 
						|
{
 | 
						|
    QHash<QString, unsigned int> cache;
 | 
						|
    for (int i = 0; i < deployList->count(); ++i) {
 | 
						|
        DeployItem &item = (*deployList)[i];
 | 
						|
        item.remoteTimeStamp
 | 
						|
                = remoteModificationTime(item.remoteFileName, &cache);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void AndroidDeployStep::filterModificationTimes(QList<DeployItem> *deployList)
 | 
						|
{
 | 
						|
    QList<DeployItem>::iterator it = deployList->begin();
 | 
						|
    while (it != deployList->end()) {
 | 
						|
        int index = it - deployList->begin();
 | 
						|
        Q_UNUSED(index);
 | 
						|
        if ((*it).localTimeStamp <= (*it).remoteTimeStamp)
 | 
						|
            it = deployList->erase(it);
 | 
						|
        else
 | 
						|
            ++it;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void AndroidDeployStep::copyFilesToTemp(QList<DeployItem> *deployList, const QString &tempDirectory, const QString &sourcePrefix)
 | 
						|
{
 | 
						|
    QDir dir;
 | 
						|
 | 
						|
    int pos = sourcePrefix.size();
 | 
						|
    for (int i = 0; i < deployList->count(); ++i) {
 | 
						|
        DeployItem &item = (*deployList)[i];
 | 
						|
        if (!item.needsStrip)
 | 
						|
            continue;
 | 
						|
        const QString destFile(tempDirectory + item.localFileName.mid(pos));
 | 
						|
        dir.mkpath(QFileInfo(destFile).absolutePath());
 | 
						|
        QFile::copy(item.localFileName, destFile);
 | 
						|
        item.localFileName = destFile;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void AndroidDeployStep::stripFiles(const QList<DeployItem> &deployList, Abi::Architecture architecture, const QString &ndkToolchainVersion)
 | 
						|
{
 | 
						|
    QProcess stripProcess;
 | 
						|
    foreach (const DeployItem &item, deployList) {
 | 
						|
        stripProcess.start(AndroidConfigurations::instance().stripPath(architecture, ndkToolchainVersion).toString(),
 | 
						|
                           QStringList()<<QLatin1String("--strip-unneeded") << item.localFileName);
 | 
						|
        stripProcess.waitForStarted();
 | 
						|
        if (!stripProcess.waitForFinished())
 | 
						|
            stripProcess.kill();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void AndroidDeployStep::deployFiles(QProcess *process, const QList<DeployItem> &deployList)
 | 
						|
{
 | 
						|
    foreach (const DeployItem &item, deployList) {
 | 
						|
        runCommand(process, AndroidConfigurations::instance().adbToolPath().toString(),
 | 
						|
                   AndroidDeviceInfo::adbSelector(m_deviceSerialNumber)
 | 
						|
                   << QLatin1String("push") << item.localFileName
 | 
						|
                   << item.remoteFileName);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
bool AndroidDeployStep::deployPackage()
 | 
						|
{
 | 
						|
    if (!m_avdName.isEmpty()) {
 | 
						|
        if (!AndroidConfigurations::instance().findAvd(m_deviceAPILevel, m_targetArch)
 | 
						|
                && !AndroidConfigurations::instance().startAVDAsync(m_avdName))
 | 
						|
            return false;
 | 
						|
        m_deviceSerialNumber = AndroidConfigurations::instance().waitForAvd(m_deviceAPILevel, m_targetArch);
 | 
						|
    }
 | 
						|
 | 
						|
    QProcess *const deployProc = new QProcess;
 | 
						|
    connect(deployProc, SIGNAL(readyReadStandardOutput()), this,
 | 
						|
        SLOT(handleBuildOutput()));
 | 
						|
    connect(deployProc, SIGNAL(readyReadStandardError()), this,
 | 
						|
        SLOT(handleBuildError()));
 | 
						|
 | 
						|
    if (m_runDeployAction == DeployLocal) {
 | 
						|
        writeOutput(tr("Deploy Qt libraries. This may take some time, please wait."));
 | 
						|
        const QString tempPath = QDir::tempPath() + QLatin1String("/android_qt_libs_") + m_packageName;
 | 
						|
        AndroidPackageCreationStep::removeDirectory(tempPath);
 | 
						|
 | 
						|
        const QString remoteRoot = QLatin1String("/data/local/tmp/qt");
 | 
						|
        QList<DeployItem> deployList;
 | 
						|
        collectFiles(&deployList,
 | 
						|
                     m_qtVersionSourcePath + QLatin1String("/lib"),
 | 
						|
                     remoteRoot + QLatin1String("/lib"),
 | 
						|
                     true,
 | 
						|
                     QStringList() << QLatin1String("*.so"));
 | 
						|
 | 
						|
        // don't use the libgnustl_shared.so from the qt directory
 | 
						|
        for (int i = 0; i < deployList.count(); ++i) {
 | 
						|
            if (deployList.at(i).remoteFileName == QLatin1String("/data/local/tmp/qt/lib/libgnustl_shared.so")) {
 | 
						|
                deployList.removeAt(i);
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        // We want to deploy that *always*
 | 
						|
        // since even if the timestamps did not change, the toolchain might have changed
 | 
						|
        // leading to a different file
 | 
						|
        deployList.append(DeployItem(m_libgnustl,
 | 
						|
                                     QDateTime::currentDateTimeUtc().toTime_t(),
 | 
						|
                                     QLatin1String("/data/local/tmp/qt/lib/libgnustl_shared.so"), false));
 | 
						|
 | 
						|
        collectFiles(&deployList,
 | 
						|
                     m_qtVersionSourcePath + QLatin1String("/plugins"),
 | 
						|
                     remoteRoot + QLatin1String("/plugins"),
 | 
						|
                     true);
 | 
						|
        collectFiles(&deployList,
 | 
						|
                     m_qtVersionSourcePath + QLatin1String("/imports"),
 | 
						|
                     remoteRoot + QLatin1String("/imports"),
 | 
						|
                     true);
 | 
						|
        collectFiles(&deployList,
 | 
						|
                     m_qtVersionSourcePath + QLatin1String("/qml"),
 | 
						|
                     remoteRoot + QLatin1String("/qml"),
 | 
						|
                     true);
 | 
						|
        collectFiles(&deployList,
 | 
						|
                     m_qtVersionSourcePath + QLatin1String("/jar"),
 | 
						|
                     remoteRoot + QLatin1String("/jar"),
 | 
						|
                     true);
 | 
						|
 | 
						|
        fetchRemoteModificationTimes(&deployList);
 | 
						|
        filterModificationTimes(&deployList);
 | 
						|
        copyFilesToTemp(&deployList, tempPath, m_qtVersionSourcePath);
 | 
						|
        stripFiles(deployList, target()->activeRunConfiguration()->abi().architecture(), m_ndkToolChainVersion);
 | 
						|
        deployFiles(deployProc, deployList);
 | 
						|
 | 
						|
        AndroidPackageCreationStep::removeDirectory(tempPath);
 | 
						|
    }
 | 
						|
 | 
						|
    deployProc->setWorkingDirectory(m_androidDirPath.toString());
 | 
						|
 | 
						|
    writeOutput(tr("Installing package onto %1.").arg(m_deviceSerialNumber));
 | 
						|
    runCommand(deployProc, AndroidConfigurations::instance().adbToolPath().toString(),
 | 
						|
               AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("uninstall") << m_packageName);
 | 
						|
    QString package = m_apkPathDebug;
 | 
						|
 | 
						|
    if (m_signPackage && QFile::exists(m_apkPathRelease))
 | 
						|
        package = m_apkPathRelease;
 | 
						|
 | 
						|
    if (!runCommand(deployProc, AndroidConfigurations::instance().adbToolPath().toString(),
 | 
						|
                    AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("install") << package)) {
 | 
						|
        raiseError(tr("Package installation failed."));
 | 
						|
        disconnect(deployProc, 0, this, 0);
 | 
						|
        deployProc->deleteLater();
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    writeOutput(tr("Pulling files necessary for debugging."));
 | 
						|
    runCommand(deployProc, AndroidConfigurations::instance().adbToolPath().toString(),
 | 
						|
               AndroidDeviceInfo::adbSelector(m_deviceSerialNumber)
 | 
						|
               << QLatin1String("pull") << QLatin1String("/system/bin/app_process")
 | 
						|
               << QString::fromLatin1("%1/app_process").arg(m_buildDirectory));
 | 
						|
    runCommand(deployProc, AndroidConfigurations::instance().adbToolPath().toString(),
 | 
						|
               AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("pull")
 | 
						|
               << QLatin1String("/system/lib/libc.so")
 | 
						|
               << QString::fromLatin1("%1/libc.so").arg(m_buildDirectory));
 | 
						|
    disconnect(deployProc, 0, this, 0);
 | 
						|
    deployProc->deleteLater();
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
void AndroidDeployStep::raiseError(const QString &errorString)
 | 
						|
{
 | 
						|
    emit addTask(Task(Task::Error, errorString, Utils::FileName::fromString(QString()), -1,
 | 
						|
        ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT));
 | 
						|
}
 | 
						|
 | 
						|
void AndroidDeployStep::writeOutput(const QString &text, OutputFormat format)
 | 
						|
{
 | 
						|
    emit addOutput(text, format);
 | 
						|
}
 | 
						|
 | 
						|
} // namespace Internal
 | 
						|
} // namespace Android
 |