From a128d38394520845d2ab8e7f6d2e016c9206667c Mon Sep 17 00:00:00 2001 From: Sergey Shambir Date: Sun, 24 Feb 2013 18:04:36 +0400 Subject: [PATCH] Android: select device with "adb -d" if it have invalid serial no Works only if no correctly detected devices attached to adb. Sometimes serial number becomes '????-????-????' on linux because udev rules are not configured, handling them without configuring will be useful. Also i have 2 phones that have no serial number at all on stock rom. Serial number disappears on some smartphones with CyanogenMod http://forum.cyanogenmod.org/topic/64522-i-have-no-serial-number/ Change-Id: I1a992eb2537342934c60d79c9180edd955aa7862 Reviewed-by: BogDan Vatra --- src/plugins/android/androidconfigurations.cpp | 37 ++++++++++++++++--- src/plugins/android/androidconfigurations.h | 2 + src/plugins/android/androiddeploystep.cpp | 22 +++++------ src/plugins/android/androidrunner.cpp | 24 +++++------- 4 files changed, 54 insertions(+), 31 deletions(-) diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index 0b37e5e51d5..149d8835305 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -350,8 +350,23 @@ QVector AndroidConfigurations::connectedDevices(int apiLevel) QList adbDevs = adbProc.readAll().trimmed().split('\n'); adbDevs.removeFirst(); AndroidDeviceInfo dev; + + // workaround for '????????????' serial numbers: + // can use "adb -d" when only one usb device attached + int usbDevicesNum = 0; + QStringList serialNumbers; foreach (const QByteArray &device, adbDevs) { - dev.serialNumber = QString::fromLatin1(device.left(device.indexOf('\t')).trimmed()); + const QString serialNo = QString::fromLatin1(device.left(device.indexOf('\t')).trimmed());; + if (!serialNo.startsWith(QLatin1String("emulator"))) + ++usbDevicesNum; + serialNumbers << serialNo; + } + + foreach (const QString &serialNo, serialNumbers) { + if (serialNo.contains(QLatin1String("????")) && usbDevicesNum > 1) + continue; + + dev.serialNumber = serialNo; dev.sdk = getSDKVersion(dev.serialNumber); if (apiLevel != -1 && dev.sdk != apiLevel) continue; @@ -522,12 +537,13 @@ QString AndroidConfigurations::startAVD(int *apiLevel, const QString &name) cons int AndroidConfigurations::getSDKVersion(const QString &device) const { + // workaround for '????????????' serial numbers + QStringList arguments = AndroidDeviceInfo::adbSelector(device); + arguments << QLatin1String("shell") << QLatin1String("getprop") + << QLatin1String("ro.build.version.sdk"); QProcess adbProc; - adbProc.start(adbToolPath().toString(), - QStringList() << QLatin1String("-s") << device - << QLatin1String("shell") << QLatin1String("getprop") - << QLatin1String("ro.build.version.sdk")); + adbProc.start(adbToolPath().toString(), arguments); if (!adbProc.waitForFinished(-1)) { adbProc.kill(); return -1; @@ -644,6 +660,17 @@ void AndroidConfigurations::updateAutomaticKitList() KitManager::instance()->registerKit(kit); } +/** + * Workaround for '????????????' serial numbers + * @return ("-d") for buggy devices, ("-s", ) for normal + */ +QStringList AndroidDeviceInfo::adbSelector(const QString &serialNumber) +{ + if (serialNumber.startsWith(QLatin1String("????"))) + return QStringList() << QLatin1String("-d"); + return QStringList() << QLatin1String("-s") << serialNumber; +} + AndroidConfigurations &AndroidConfigurations::instance(QObject *parent) { if (m_instance == 0) diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h index 44ee284db72..50dce7a3edf 100644 --- a/src/plugins/android/androidconfigurations.h +++ b/src/plugins/android/androidconfigurations.h @@ -78,6 +78,8 @@ struct AndroidDeviceInfo QString serialNumber; QString cpuABI; int sdk; + + static QStringList adbSelector(const QString &serialNumber); }; class AndroidConfigurations : public QObject diff --git a/src/plugins/android/androiddeploystep.cpp b/src/plugins/android/androiddeploystep.cpp index 73ab60777e3..759243cf7e7 100644 --- a/src/plugins/android/androiddeploystep.cpp +++ b/src/plugins/android/androiddeploystep.cpp @@ -172,9 +172,8 @@ void AndroidDeployStep::cleanLibsOnDevice() return; } QProcess *process = new QProcess(this); - QStringList arguments; - arguments << QLatin1String("-s") << deviceSerialNumber - << QLatin1String("shell") << QLatin1String("rm") << QLatin1String("-r") << QLatin1String("/data/local/tmp/qt"); + QStringList arguments = AndroidDeviceInfo::adbSelector(deviceSerialNumber); + arguments << QLatin1String("shell") << QLatin1String("rm") << QLatin1String("-r") << QLatin1String("/data/local/tmp/qt"); connect(process, SIGNAL(finished(int)), this, SLOT(cleanLibsFinished())); const QString adb = AndroidConfigurations::instance().adbToolPath().toString(); Core::MessageManager::instance()->printToOutputPanePopup(adb + QLatin1String(" ") @@ -275,9 +274,8 @@ unsigned int AndroidDeployStep::remoteModificationTime(const QString &fullDestin QHash::const_iterator it = cache->find(fullDestination); if (it != cache->constEnd()) return *it; - QStringList arguments; - arguments << QLatin1String("-s") << m_deviceSerialNumber - << QLatin1String("ls") << destination; + 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 @@ -378,7 +376,7 @@ void AndroidDeployStep::deployFiles(QProcess *process, const QList & { foreach (const DeployItem &item, deployList) { runCommand(process, AndroidConfigurations::instance().adbToolPath().toString(), - QStringList() << QLatin1String("-s") << m_deviceSerialNumber + AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("push") << item.localFileName << item.remoteFileName); } @@ -432,7 +430,7 @@ bool AndroidDeployStep::deployPackage() if (m_runDeployAction == InstallQASI) { if (!runCommand(deployProc, AndroidConfigurations::instance().adbToolPath().toString(), - QStringList() << QLatin1String("-s") << m_deviceSerialNumber + AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("install") << QLatin1String("-r ") << m_runQASIPackagePath)) { raiseError(tr("Qt Android smart installer installation failed")); disconnect(deployProc, 0, this, 0); @@ -445,7 +443,7 @@ bool AndroidDeployStep::deployPackage() writeOutput(tr("Installing package onto %1.").arg(m_deviceSerialNumber)); runCommand(deployProc, AndroidConfigurations::instance().adbToolPath().toString(), - QStringList() << QLatin1String("-s") << m_deviceSerialNumber << QLatin1String("uninstall") << m_packageName); + AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("uninstall") << m_packageName); QString package = m_apkPathDebug; if (!(m_qtVersionQMakeBuildConfig & QtSupport::BaseQtVersion::DebugBuild) @@ -453,7 +451,7 @@ bool AndroidDeployStep::deployPackage() package = m_apkPathRelease; if (!runCommand(deployProc, AndroidConfigurations::instance().adbToolPath().toString(), - QStringList() << QLatin1String("-s") << m_deviceSerialNumber << QLatin1String("install") << package)) { + AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("install") << package)) { raiseError(tr("Package installation failed.")); disconnect(deployProc, 0, this, 0); deployProc->deleteLater(); @@ -462,11 +460,11 @@ bool AndroidDeployStep::deployPackage() writeOutput(tr("Pulling files necessary for debugging.")); runCommand(deployProc, AndroidConfigurations::instance().adbToolPath().toString(), - QStringList() << QLatin1String("-s") << m_deviceSerialNumber + 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(), - QStringList() << QLatin1String("-s") << m_deviceSerialNumber << QLatin1String("pull") + AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("pull") << QLatin1String("/system/lib/libc.so") << QString::fromLatin1("%1/libc.so").arg(m_buildDirectory)); disconnect(deployProc, 0, this, 0); diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp index 02373108f38..7b7d9633437 100644 --- a/src/plugins/android/androidrunner.cpp +++ b/src/plugins/android/androidrunner.cpp @@ -80,7 +80,7 @@ void AndroidRunner::checkPID() // Detect busybox, as we need to pass -w to it to get wide output. psProc.start(AndroidConfigurations::instance().adbToolPath().toString(), - QStringList() << QLatin1String("-s") << m_deviceSerialNumber + AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("shell") << QLatin1String("readlink") << QLatin1String("$(which ps)")); if (!psProc.waitForFinished(-1)) { psProc.kill(); @@ -93,7 +93,7 @@ void AndroidRunner::checkPID() } psProc.start(AndroidConfigurations::instance().adbToolPath().toString(), - QStringList() << QLatin1String("-s") << m_deviceSerialNumber + AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("shell") << psCmd); if (!psProc.waitForFinished(-1)) { psProc.kill(); @@ -161,9 +161,8 @@ void AndroidRunner::asyncStart() QString extraParams; QProcess adbStarProc; if (m_useCppDebugger) { - QStringList arguments; - arguments << QLatin1String("-s") << m_deviceSerialNumber - << QLatin1String("forward") << QString::fromLatin1("tcp%1").arg(m_remoteGdbChannel) + QStringList arguments = AndroidDeviceInfo::adbSelector(m_deviceSerialNumber); + arguments << QLatin1String("forward") << QString::fromLatin1("tcp%1").arg(m_remoteGdbChannel) << QString::fromLatin1("localfilesystem:/data/data/%1/debug-socket").arg(m_packageName); adbStarProc.start(AndroidConfigurations::instance().adbToolPath().toString(), arguments); if (!adbStarProc.waitForStarted()) { @@ -177,10 +176,9 @@ void AndroidRunner::asyncStart() extraParams = QLatin1String("-e native_debug true -e gdbserver_socket +debug-socket"); } if (m_useQmlDebugger) { - QStringList arguments; + QStringList arguments = AndroidDeviceInfo::adbSelector(m_deviceSerialNumber); QString port = QString::fromLatin1("tcp:%1").arg(m_qmlPort); - arguments << QLatin1String("-s") << m_deviceSerialNumber - << QLatin1String("forward") << port << port; // currently forward to same port on device and host + arguments << QLatin1String("forward") << port << port; // currently forward to same port on device and host adbStarProc.start(AndroidConfigurations::instance().adbToolPath().toString(), arguments); if (!adbStarProc.waitForStarted()) { emit remoteProcessFinished(tr("Failed to forward QML debugging ports. Reason: %1.").arg(adbStarProc.errorString())); @@ -204,9 +202,8 @@ void AndroidRunner::asyncStart() } extraParams = extraParams.trimmed(); - QStringList arguments; - arguments << QLatin1String("-s") << m_deviceSerialNumber - << QLatin1String("shell") << QLatin1String("am") + QStringList arguments = AndroidDeviceInfo::adbSelector(m_deviceSerialNumber); + arguments << QLatin1String("shell") << QLatin1String("am") << QLatin1String("start") << QLatin1String("-n") << m_intentName; if (extraParams.length()) @@ -246,7 +243,7 @@ void AndroidRunner::startLogcat() { m_checkPIDTimer.start(1000); // check if the application is alive every 1 seconds m_adbLogcatProcess.start(AndroidConfigurations::instance().adbToolPath().toString(), - QStringList() << QLatin1String("-s") << m_deviceSerialNumber + AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("logcat")); emit remoteProcessStarted(5039); } @@ -294,9 +291,8 @@ void AndroidRunner::logcatReadStandardOutput() void AndroidRunner::adbKill(qint64 pid, const QString &device, int timeout, const QString &runAsPackageName) { QProcess process; - QStringList arguments; + QStringList arguments = AndroidDeviceInfo::adbSelector(device); - arguments << QLatin1String("-s") << device; arguments << QLatin1String("shell"); if (runAsPackageName.size()) arguments << QLatin1String("run-as") << runAsPackageName;