Use secure apis and mount developer disk image on device

Add code to find the developer disk image in xcode installation
based on the device version and build number

Change-Id: Ic05795ad9411ef0f3713c58dc9d286bf6ad1fa19
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Vikas Pachdha
2016-04-18 17:32:03 +02:00
parent d7f8af9392
commit a2e2db0051

View File

@@ -51,6 +51,12 @@
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CFRunLoop.h>
#include <CoreFoundation/CFDictionary.h>
#include <CoreFoundation/CFData.h>
#include <QDir>
#include <QFile>
#include <QProcess>
#ifdef MOBILE_DEV_DIRECT_LINK
#include "MobileDevice.h"
@@ -89,9 +95,12 @@ struct AMDeviceNotificationCallbackInfo {
};
typedef void (MDEV_API *AMDeviceNotificationCallback)(AMDeviceNotificationCallbackInfo *, void *);
typedef am_res_t (MDEV_API *AMDeviceInstallApplicationCallback)(CFDictionaryRef, void *);
typedef mach_error_t (MDEV_API *AMDeviceSecureInstallApplicationCallback)(CFDictionaryRef, int);
typedef AMDevice *AMDeviceRef;
#endif
typedef am_res_t (MDEV_API *AMDeviceMountImageCallback)(void *, void *);
typedef void (MDEV_API *AMDeviceMountImageCallback)(CFDictionaryRef, int);
@@ -113,17 +122,16 @@ typedef am_res_t (MDEV_API *AMDeviceDisconnectPtr)(AMDeviceRef);
typedef am_res_t (MDEV_API *AMDeviceMountImagePtr)(AMDeviceRef, CFStringRef, CFDictionaryRef,
AMDeviceMountImageCallback, void *);
typedef am_res_t (MDEV_API *AMDeviceStartServicePtr)(AMDeviceRef, CFStringRef, ServiceSocket *, void *);
typedef am_res_t (MDEV_API *AMDeviceTransferApplicationPtr)(ServiceSocket, CFStringRef, CFDictionaryRef,
AMDeviceInstallApplicationCallback,
void *);
typedef am_res_t (MDEV_API *AMDeviceInstallApplicationPtr)(ServiceSocket, CFStringRef, CFDictionaryRef,
AMDeviceInstallApplicationCallback,
void*);
typedef am_res_t (MDEV_API *AMDeviceUninstallApplicationPtr)(ServiceSocket, CFStringRef, CFDictionaryRef,
AMDeviceInstallApplicationCallback,
void*);
typedef am_res_t (MDEV_API *AMDeviceLookupApplicationsPtr)(AMDeviceRef, CFDictionaryRef, CFDictionaryRef *);
typedef am_res_t (MDEV_API *USBMuxConnectByPortPtr)(unsigned int, int, ServiceSocket*);
// secure Api's
typedef am_res_t (MDEV_API *AMDeviceSecureStartServicePtr)(AMDeviceRef, CFStringRef, void *, ServiceSocket *);
typedef int (MDEV_API *AMDeviceSecureTransferPathPtr)(int, AMDeviceRef, CFURLRef, CFDictionaryRef, AMDeviceSecureInstallApplicationCallback, int);
typedef int (MDEV_API *AMDeviceSecureInstallApplicationPtr)(int, AMDeviceRef, CFURLRef, CFDictionaryRef, AMDeviceSecureInstallApplicationCallback, int);
} // extern C
@@ -372,12 +380,6 @@ public :
am_res_t deviceMountImage(AMDeviceRef, CFStringRef, CFDictionaryRef,
AMDeviceMountImageCallback, void *);
am_res_t deviceStartService(AMDeviceRef, CFStringRef, ServiceSocket *, void *);
am_res_t deviceTransferApplication(int, CFStringRef, CFDictionaryRef,
AMDeviceInstallApplicationCallback,
void *);
am_res_t deviceInstallApplication(int, CFStringRef, CFDictionaryRef,
AMDeviceInstallApplicationCallback,
void*);
am_res_t deviceUninstallApplication(int, CFStringRef, CFDictionaryRef,
AMDeviceInstallApplicationCallback,
void*);
@@ -386,6 +388,14 @@ public :
void addError(const QString &msg);
void addError(const char *msg);
// Secure API's
am_res_t deviceSecureStartService(AMDeviceRef, CFStringRef, void *, ServiceSocket *);
int deviceSecureTransferApplicationPath(int, AMDeviceRef, CFURLRef,
CFDictionaryRef, AMDeviceSecureInstallApplicationCallback callback, int);
int deviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url,
CFDictionaryRef options, AMDeviceSecureInstallApplicationCallback callback, int arg);
QStringList m_errors;
private:
QLibrary lib;
@@ -405,8 +415,9 @@ private:
AMDeviceDisconnectPtr m_AMDeviceDisconnect;
AMDeviceMountImagePtr m_AMDeviceMountImage;
AMDeviceStartServicePtr m_AMDeviceStartService;
AMDeviceTransferApplicationPtr m_AMDeviceTransferApplication;
AMDeviceInstallApplicationPtr m_AMDeviceInstallApplication;
AMDeviceSecureStartServicePtr m_AMDeviceSecureStartService;
AMDeviceSecureTransferPathPtr m_AMDeviceSecureTransferPath;
AMDeviceSecureInstallApplicationPtr m_AMDeviceSecureInstallApplication;
AMDeviceUninstallApplicationPtr m_AMDeviceUninstallApplication;
AMDeviceLookupApplicationsPtr m_AMDeviceLookupApplications;
USBMuxConnectByPortPtr m_USBMuxConnectByPort;
@@ -446,10 +457,12 @@ public:
int qmljsDebugPort() const override;
void addError(const QString &msg);
bool writeAll(ServiceSocket fd, const char *cmd, qptrdiff len = -1);
bool mountDeveloperDiskImage();
bool sendGdbCommand(ServiceSocket fd, const char *cmd, qptrdiff len = -1);
QByteArray readGdbReply(ServiceSocket fd);
bool expectGdbReply(ServiceSocket gdbFd, QByteArray expected);
bool expectGdbOkReply(ServiceSocket gdbFd);
bool startServiceSecure(const QString &serviceName, ServiceSocket &fd);
MobileDeviceLib *lib();
@@ -457,6 +470,11 @@ public:
int progressBase;
int unexpectedChars;
bool aknowledge;
private:
bool developerDiskImagePath(QString *path, QString *signaturePath);
bool findDeveloperDiskImage(QString *diskImagePath, QString versionString, QString buildString);
private:
bool checkRead(qptrdiff nRead, int &maxRetry);
int handleChar(int sock, QByteArray &res, char c, int status);
@@ -598,6 +616,38 @@ extern "C" am_res_t appTransferSessionCallback(CFDictionaryRef dict, void *userD
return session->appTransferCallback(dict);
}
extern "C" mach_error_t appSecureTransferSessionCallback(CFDictionaryRef dict, int arg)
{
Q_UNUSED(arg)
CFStringRef cfStatus = reinterpret_cast<CFStringRef>(CFDictionaryGetValue(dict, CFSTR("Status")));
const QString status = QString::fromCFString(cfStatus);
quint32 percent = 0;
CFNumberRef cfProgress;
if (CFDictionaryGetValueIfPresent(dict, CFSTR("PercentComplete"), reinterpret_cast<const void **>(&cfProgress))) {
if (cfProgress && CFGetTypeID(cfProgress) == CFNumberGetTypeID())
CFNumberGetValue(cfProgress, kCFNumberSInt32Type, reinterpret_cast<const void **>(&percent));
}
QString path;
if (status == "CopyingFile") {
CFStringRef cfPath = reinterpret_cast<CFStringRef>(CFDictionaryGetValue(dict, CFSTR("Path")));
path = QString::fromCFString(cfPath);
}
if (debugAll) {
qDebug() << "["<<percent<<"]" << status << path;
} else {
static QString oldStatus;
if (oldStatus != status) {
qDebug() << status;
oldStatus = status;
}
}
return 0;
}
extern "C" am_res_t appInstallSessionCallback(CFDictionaryRef dict, void *userData)
{
if (debugAll) {
@@ -936,26 +986,27 @@ bool CommandSession::connectDevice()
{
if (!device)
return false;
if (am_res_t error1 = lib()->deviceConnect(device)) {
addError(QString::fromLatin1("connectDevice %1 failed, AMDeviceConnect returned %2")
.arg(deviceId).arg(error1));
addError(QString::fromLatin1("connectDevice %1 failed, AMDeviceConnect returned %2 (0x%3)")
.arg(deviceId).arg(mobileDeviceErrorString(error1)).arg(error1));
return false;
}
if (lib()->deviceIsPaired(device) == 0) { // not paired
if (am_res_t error = lib()->devicePair(device)) {
addError(QString::fromLatin1("connectDevice %1 failed, AMDevicePair returned %2")
.arg(deviceId).arg(error));
addError(QString::fromLatin1("connectDevice %1 failed, AMDevicePair returned %2 (0x%3)")
.arg(deviceId).arg(mobileDeviceErrorString(error)).arg(error));
return false;
}
}
if (am_res_t error2 = lib()->deviceValidatePairing(device)) {
addError(QString::fromLatin1("connectDevice %1 failed, AMDeviceValidatePairing returned %2")
.arg(deviceId).arg(error2));
addError(QString::fromLatin1("connectDevice %1 failed, AMDeviceValidatePairing returned %2 (0x%3)")
.arg(deviceId).arg(mobileDeviceErrorString(error2)).arg(error2));
return false;
}
if (am_res_t error3 = lib()->deviceStartSession(device)) {
addError(QString::fromLatin1("connectDevice %1 failed, AMDeviceStartSession returned %2")
.arg(deviceId).arg(error3));
addError(QString::fromLatin1("connectDevice %1 failed, AMDeviceStartSession returned %2 (0x%3)")
.arg(deviceId).arg(mobileDeviceErrorString(error3)).arg(error3));
return false;
}
return true;
@@ -964,13 +1015,13 @@ bool CommandSession::connectDevice()
bool CommandSession::disconnectDevice()
{
if (am_res_t error = lib()->deviceStopSession(device)) {
addError(QString::fromLatin1("stopSession %1 failed, AMDeviceStopSession returned %2")
.arg(deviceId).arg(error));
addError(QString::fromLatin1("stopSession %1 failed, AMDeviceStopSession returned %2 (0x%3)")
.arg(deviceId).arg(mobileDeviceErrorString(error)).arg(error));
return false;
}
if (am_res_t error = lib()->deviceDisconnect(device)) {
addError(QString::fromLatin1("disconnectDevice %1 failed, AMDeviceDisconnect returned %2")
.arg(deviceId).arg(error));
addError(QString::fromLatin1("disconnectDevice %1 failed, AMDeviceDisconnect returned %2 (0x%3)")
.arg(deviceId).arg(mobileDeviceErrorString(error)).arg(error));
return false;
}
return true;
@@ -978,20 +1029,50 @@ bool CommandSession::disconnectDevice()
bool CommandSession::startService(const QString &serviceName, ServiceSocket &fd)
{
bool failure = false;
fd = 0;
if (!connectDevice())
return false;
CFStringRef cfsService = serviceName.toCFString();
if (am_res_t error = lib()->deviceStartService(device, cfsService, &fd, 0)) {
addError(QString::fromLatin1("Starting service \"%1\" on device %2 failed, AMDeviceStartService returned %3 (0x%4)")
.arg(serviceName).arg(deviceId).arg(mobileDeviceErrorString(error)).arg(QString::number(error, 16)));
failure = true;
fd = -1;
bool success = true;
// Connect device. AMDeviceConnect + AMDeviceIsPaired + AMDeviceValidatePairing + AMDeviceStartSession
if (connectDevice()) {
fd = 0;
CFStringRef cfsService = serviceName.toCFString();
if (am_res_t error = lib()->deviceStartService(device, cfsService, &fd, 0)) {
addError(QString::fromLatin1("Starting service \"%1\" on device %2 failed, AMDeviceStartService returned %3 (0x%4)")
.arg(serviceName).arg(deviceId).arg(mobileDeviceErrorString(error)).arg(QString::number(error, 16)));
success = false;
fd = -1;
}
disconnectDevice();
CFRelease(cfsService);
} else {
addError(QString::fromLatin1("Starting service \"%1\" on device %2 failed. Cannot connect to device.")
.arg(serviceName).arg(deviceId));
success = false;
}
CFRelease(cfsService);
disconnectDevice();
return !failure;
return success;
}
bool CommandSession::startServiceSecure(const QString &serviceName, ServiceSocket &fd)
{
bool success = true;
// Connect device. AMDeviceConnect + AMDeviceIsPaired + AMDeviceValidatePairing + AMDeviceStartSession
if (connectDevice()) {
fd = 0;
CFStringRef cfsService = serviceName.toCFString();
if (am_res_t error = lib()->deviceSecureStartService(device, cfsService, &fd, 0)) {
addError(QString::fromLatin1("Starting(Secure) service \"%1\" on device %2 failed, AMDeviceStartSecureService returned %3 (0x%4)")
.arg(serviceName).arg(deviceId).arg(mobileDeviceErrorString(error)).arg(QString::number(error, 16)));
success = false;
fd = -1;
}
disconnectDevice();
CFRelease(cfsService);
} else {
addError(QString::fromLatin1("Starting(Secure) service \"%1\" on device %2 failed. Cannot connect to device.")
.arg(serviceName).arg(deviceId));
success = false;
}
return success;
}
bool CommandSession::connectToPort(quint16 port, ServiceSocket *fd)
@@ -1076,6 +1157,55 @@ bool CommandSession::writeAll(ServiceSocket fd, const char *cmd, qptrdiff len)
return true;
}
void mountCallback(CFDictionaryRef dict, int arg)
{
Q_UNUSED(arg)
CFStringRef cfStatus = reinterpret_cast<CFStringRef>(CFDictionaryGetValue(dict, CFSTR("Status")));
qDebug() << "Mounting dev Image :"<<QString::fromCFString(cfStatus);
}
bool CommandSession::mountDeveloperDiskImage() {
bool success = false;
QString imagePath;
QString signaturePath;
if (developerDiskImagePath(&imagePath, &signaturePath)) {
QFile sigFile(signaturePath);
if (sigFile.open(QFile::ReadOnly)) {
// Read the signature.
const QByteArray signatureData = sigFile.read(128);
sigFile.close();
CFDataRef sig_data = signatureData.toRawCFData();
CFTypeRef keys[] = { CFSTR("ImageSignature"), CFSTR("ImageType") };
CFTypeRef values[] = { sig_data, CFSTR("Developer") };
CFDictionaryRef options = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values,
2, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (connectDevice()) {
CFStringRef cfImgPath = imagePath.toCFString();
if (am_res_t result = lib()->deviceMountImage(device, cfImgPath, options, &mountCallback, 0)) {
addError(QString::fromLatin1("Mount Developer Disk Image \"%1\" failed, AMDeviceMountImage returned %2 (0x%3)")
.arg(imagePath).arg(mobileDeviceErrorString(result)).arg(QString::number(result, 16)));
} else {
// Mounting succeeded.
success = true;
}
CFRelease(cfImgPath);
disconnectDevice();
} else
addError(QString::fromLatin1("Mount Developer Disk Image \"%1\" failed. Cannot connect to device \"%2\".")
.arg(imagePath).arg(deviceId));
} else {
addError(QString::fromLatin1("Mount Developer Disk Image \"%1\" failed. Unable to open disk image.")
.arg(imagePath));
}
} else {
addError(QString::fromLatin1("Mount Developer Disk Image failed. Unable to fetch developer disk image path."));
}
return success;
}
bool CommandSession::sendGdbCommand(ServiceSocket fd, const char *cmd, qptrdiff len)
{
if (len == -1)
@@ -1248,6 +1378,101 @@ MobileDeviceLib *CommandSession::lib()
return IosDeviceManagerPrivate::instance()->lib();
}
bool CommandSession::developerDiskImagePath(QString *path, QString *signaturePath)
{
bool success = false;
if (device && path && connectDevice()) {
CFPropertyListRef cfProductVersion = lib()->deviceCopyValue(device, 0, CFSTR("ProductVersion"));
QString versionString;
if (cfProductVersion && CFGetTypeID(cfProductVersion) == CFStringGetTypeID()) {
versionString = QString::fromCFString(reinterpret_cast<CFStringRef>(cfProductVersion));
}
CFRelease(cfProductVersion);
CFPropertyListRef cfBuildVersion = lib()->deviceCopyValue(device, 0, CFSTR("BuildVersion"));
QString buildString;
if (cfBuildVersion && CFGetTypeID(cfBuildVersion) == CFStringGetTypeID()) {
buildString = QString::fromCFString(reinterpret_cast<CFStringRef>(cfBuildVersion));
}
CFRelease(cfBuildVersion);
disconnectDevice();
if (findDeveloperDiskImage(path, versionString, buildString)) {
success = QFile::exists(*path);
if (success && debugAll)
qDebug() << "Developers disk image found at" << path;
if (success && signaturePath) {
*signaturePath = QString("%1.%2").arg(*path).arg("signature");
success = QFile::exists(*signaturePath);
}
}
}
return success;
}
bool CommandSession::findDeveloperDiskImage(QString *diskImagePath, QString versionString, QString buildString)
{
if (!diskImagePath || versionString.isEmpty())
return false;
*diskImagePath = QString();
QProcess process;
process.start("/bin/bash", QStringList() << "-c" << "xcode-select -p");
if (!process.waitForFinished(3000))
addError("Error getting xcode installation path. Command did not finish in time");
const QString xcodePath = QString::fromLatin1(process.readAllStandardOutput()).trimmed();
if (process.exitStatus() == QProcess::NormalExit && QFile::exists(xcodePath)) {
auto imageExists = [xcodePath](QString *foundPath, QString subFolder, QString version, QString build) -> bool {
Q_ASSERT(foundPath);
const QString subFolderPath = QString("%1/%2").arg(xcodePath).arg(subFolder);
if (QFile::exists(subFolderPath)) {
*foundPath = QString("%1/%2 (%3)/DeveloperDiskImage.dmg").arg(subFolderPath).arg(version).arg(build);
if (QFile::exists(*foundPath)) {
return true;
}
QDir subFolderDir(subFolderPath);
QStringList nameFilterList;
nameFilterList << QString("%1 (*)").arg(version);
QFileInfoList builds = subFolderDir.entryInfoList(nameFilterList, QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed);
foreach (QFileInfo buildPathInfo, builds) {
*foundPath = QString("%1/DeveloperDiskImage.dmg").arg(buildPathInfo.absoluteFilePath());
if (QFile::exists(*foundPath)) {
return true;
}
}
*foundPath = QString("%1/%2/DeveloperDiskImage.dmg").arg(subFolderPath).arg(version);
if (QFile::exists(*foundPath)) {
return true;
}
}
*foundPath = QString();
return false;
};
QStringList versionParts = versionString.split(".", QString::SkipEmptyParts);
while (versionParts.count() > 0) {
if (imageExists(diskImagePath,"iOS DeviceSupport", versionParts.join("."), buildString))
break;
if (imageExists(diskImagePath,"Platforms/iPhoneOS.platform/DeviceSupport", versionParts.join("."), buildString))
break;
const QString latestImagePath = QString("%1/Platforms/iPhoneOS.platform/DeviceSupport/Latest/DeveloperDiskImage.dmg").arg(xcodePath);
if (QFile::exists(latestImagePath)) {
*diskImagePath = latestImagePath;
break;
}
versionParts.removeLast();
}
}
return !diskImagePath->isEmpty();
}
AppOpSession::AppOpSession(const QString &deviceId, const QString &bundlePath,
const QStringList &extraArgs, IosDeviceManager::AppOp appOp):
CommandSession(deviceId), bundlePath(bundlePath), extraArgs(extraArgs), appOp(appOp)
@@ -1260,66 +1485,70 @@ QString AppOpSession::commandName()
bool AppOpSession::installApp()
{
ServiceSocket fd;
bool failure = (device == 0);
if (!failure) {
failure = !startService(QLatin1String("com.apple.afc"), fd);
if (!failure) {
CFStringRef cfsBundlePath = bundlePath.toCFString();
if (am_res_t error = lib()->deviceTransferApplication(fd, cfsBundlePath, 0,
&appTransferSessionCallback,
static_cast<CommandSession *>(this))) {
addError(QString::fromLatin1("TransferAppSession(%1,%2) failed, AMDeviceTransferApplication returned %3 (0x%4)")
.arg(bundlePath, deviceId).arg(mobileDeviceErrorString(error)).arg(error));
failure = true;
}
progressBase += 100;
CFRelease(cfsBundlePath);
}
stopService(fd);
}
if (debugAll)
qDebug() << "AMDeviceTransferApplication finished request with " << failure;
if (!failure) {
failure = !startService(QLatin1String("com.apple.mobile.installation_proxy"), fd);
if (!failure) {
CFStringRef cfsBundlePath = bundlePath.toCFString();
bool success = false;
if (device != 0) {
CFURLRef bundleUrl = QUrl::fromLocalFile(bundlePath).toCFURL();
CFStringRef key[1] = {CFSTR("PackageType")};
CFStringRef value[1] = {CFSTR("Developer")};
CFDictionaryRef options = CFDictionaryCreate(0, reinterpret_cast<const void**>(&key[0]),
reinterpret_cast<const void**>(&value[0]), 1,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFStringRef key[1] = {CFSTR("PackageType")};
CFStringRef value[1] = {CFSTR("Developer")};
CFDictionaryRef options = CFDictionaryCreate(0, reinterpret_cast<const void**>(&key[0]),
reinterpret_cast<const void**>(&value[0]), 1,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (am_res_t error = lib()->deviceInstallApplication(fd, cfsBundlePath, options,
&appInstallSessionCallback,
static_cast<CommandSession *>(this))) {
const QString errorString = mobileDeviceErrorString(error);
if (!errorString.isEmpty())
addError(errorString
+ QStringLiteral(" (0x")
+ QString::number(error, 16)
+ QStringLiteral(")"));
else
addError(QString::fromLatin1("InstallAppSession(%1,%2) failed, "
"AMDeviceInstallApplication returned 0x%3")
.arg(bundlePath, deviceId).arg(QString::number(error, 16)));
failure = true;
// Transfer bundle with secure API AMDeviceTransferApplication.
if (int error = lib()->deviceSecureTransferApplicationPath(0, device, bundleUrl, options,
&appSecureTransferSessionCallback,0)) {
addError(QString::fromLatin1("TransferAppSession(%1,%2) failed, AMDeviceTransferApplication returned %3 (0x%4)")
.arg(bundlePath, deviceId).arg(mobileDeviceErrorString(error)).arg(error));
success = false;
} else {
// App is transferred. Try installing.
if (connectDevice()) {
// Secure install app api requires device to be connected.
if (am_res_t error = lib()->deviceSecureInstallApplication(0, device, bundleUrl, options,
&appSecureTransferSessionCallback,0)) {
const QString errorString = mobileDeviceErrorString(error);
if (!errorString.isEmpty()) {
addError(errorString
+ QStringLiteral(" (0x")
+ QString::number(error, 16)
+ QStringLiteral(")"));
} else {
addError(QString::fromLatin1("InstallAppSession(%1,%2) failed, "
"AMDeviceInstallApplication returned 0x%3")
.arg(bundlePath, deviceId).arg(QString::number(error, 16)));
}
success = false;
} else {
// App is installed.
success = true;
}
disconnectDevice();
}
progressBase += 100;
CFRelease(options);
CFRelease(cfsBundlePath);
}
stopService(fd);
if (debugAll) {
qDebug() << "AMDeviceSecureTransferApplication finished request with " << (success ? "Success" : "Failure");
}
CFRelease(options);
CFRelease(bundleUrl);
progressBase += 100;
}
if (!failure)
if (success) {
sleep(5); // after installation the device needs a bit of quiet....
if (debugAll)
qDebug() << "AMDeviceInstallApplication finished request with " << failure;
}
if (debugAll) {
qDebug() << "AMDeviceSecureInstallApplication finished request with " << (success ? "Success" : "Failure");
}
IosDeviceManagerPrivate::instance()->didTransferApp(bundlePath, deviceId,
(failure ? IosDeviceManager::Failure : IosDeviceManager::Success));
return !failure;
(success ? IosDeviceManager::Success : IosDeviceManager::Failure));
return success;
}
void AppOpSession::deviceCallbackReturned()
@@ -1354,13 +1583,19 @@ int AppOpSession::qmljsDebugPort() const
return 0;
}
bool AppOpSession::runApp()
{
bool failure = (device == 0);
QString exe = appPathOnDevice();
ServiceSocket gdbFd = -1;
if (!mountDeveloperDiskImage()) {
addError(QString::fromLatin1("Running app \"%1\" failed. Mount developer disk failed.").arg(bundlePath));
failure = true;
}
if (!failure && !startService(QLatin1String("com.apple.debugserver"), gdbFd))
gdbFd = -1;
if (gdbFd > 0) {
// gdbServer protocol, see http://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html#Remote-Protocol
// and the lldb handling of that (with apple specific stuff)
@@ -1648,12 +1883,15 @@ bool MobileDeviceLib::load()
m_AMDeviceStartService = reinterpret_cast<AMDeviceStartServicePtr>(lib.resolve("AMDeviceStartService"));
if (m_AMDeviceStartService == 0)
addError("MobileDeviceLib does not define AMDeviceStartService");
m_AMDeviceTransferApplication = reinterpret_cast<AMDeviceTransferApplicationPtr>(lib.resolve("AMDeviceTransferApplication"));
if (m_AMDeviceTransferApplication == 0)
addError("MobileDeviceLib does not define AMDeviceTransferApplication");
m_AMDeviceInstallApplication = reinterpret_cast<AMDeviceInstallApplicationPtr>(lib.resolve("AMDeviceInstallApplication"));
if (m_AMDeviceInstallApplication == 0)
addError("MobileDeviceLib does not define AMDeviceInstallApplication");
m_AMDeviceSecureStartService = reinterpret_cast<AMDeviceSecureStartServicePtr>(lib.resolve("AMDeviceSecureStartService"));
if (m_AMDeviceSecureStartService == 0)
addError("MobileDeviceLib does not define AMDeviceSecureStartService");
m_AMDeviceSecureTransferPath = reinterpret_cast<AMDeviceSecureTransferPathPtr>(lib.resolve("AMDeviceSecureTransferPath"));
if (m_AMDeviceSecureTransferPath == 0)
addError("MobileDeviceLib does not define AMDeviceSecureTransferPath");
m_AMDeviceSecureInstallApplication = reinterpret_cast<AMDeviceSecureInstallApplicationPtr>(lib.resolve("AMDeviceSecureInstallApplication"));
if (m_AMDeviceSecureInstallApplication == 0)
addError("MobileDeviceLib does not define AMDeviceSecureInstallApplication");
m_AMDeviceUninstallApplication = reinterpret_cast<AMDeviceUninstallApplicationPtr>(lib.resolve("AMDeviceUninstallApplication"));
if (m_AMDeviceUninstallApplication == 0)
addError("MobileDeviceLib does not define AMDeviceUninstallApplication");
@@ -1772,7 +2010,7 @@ am_res_t MobileDeviceLib::deviceDisconnect(AMDeviceRef device)
am_res_t MobileDeviceLib::deviceMountImage(AMDeviceRef device, CFStringRef imagePath,
CFDictionaryRef options,
AMDeviceMountImageCallback callback,
void * callbackExtraArgs)
void *callbackExtraArgs)
{
if (m_AMDeviceMountImage)
return m_AMDeviceMountImage(device, imagePath, options, callback, callbackExtraArgs);
@@ -1787,30 +2025,11 @@ am_res_t MobileDeviceLib::deviceStartService(AMDeviceRef device, CFStringRef ser
return -1;
}
am_res_t MobileDeviceLib::deviceTransferApplication(int serviceFd, CFStringRef appPath,
CFDictionaryRef options,
AMDeviceInstallApplicationCallback callback,
void *callbackExtraArgs)
{
if (m_AMDeviceTransferApplication)
return m_AMDeviceTransferApplication(serviceFd, appPath, options, callback, callbackExtraArgs);
return -1;
}
am_res_t MobileDeviceLib::deviceInstallApplication(int serviceFd, CFStringRef appPath,
CFDictionaryRef options,
AMDeviceInstallApplicationCallback callback,
void *callbackExtraArgs)
{
if (m_AMDeviceInstallApplication)
return m_AMDeviceInstallApplication(serviceFd, appPath, options, callback, callbackExtraArgs);
return -1;
}
am_res_t MobileDeviceLib::deviceUninstallApplication(int serviceFd, CFStringRef bundleId,
CFDictionaryRef options,
AMDeviceInstallApplicationCallback callback,
void* callbackExtraArgs)
void *callbackExtraArgs)
{
if (m_AMDeviceUninstallApplication)
return m_AMDeviceUninstallApplication(serviceFd, bundleId, options, callback, callbackExtraArgs);
@@ -1843,6 +2062,31 @@ void MobileDeviceLib::addError(const char *msg)
addError(QLatin1String(msg));
}
am_res_t MobileDeviceLib::deviceSecureStartService(AMDeviceRef device, CFStringRef serviceName, void *extra, ServiceSocket *fdRef)
{
int returnCode = -1;
if (m_AMDeviceSecureStartService)
returnCode = m_AMDeviceSecureStartService(device, serviceName, extra, fdRef);
return returnCode;
}
int MobileDeviceLib::deviceSecureTransferApplicationPath(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef dict, AMDeviceSecureInstallApplicationCallback callback, int args)
{
int returnCode = -1;
if (m_AMDeviceSecureTransferPath)
returnCode = m_AMDeviceSecureTransferPath(zero, device, url, dict, callback, args);
return returnCode;
}
int MobileDeviceLib::deviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, AMDeviceSecureInstallApplicationCallback callback, int arg)
{
int returnCode = -1;
if (m_AMDeviceSecureInstallApplication) {
returnCode = m_AMDeviceSecureInstallApplication(zero, device, url, options, callback, arg);
}
return returnCode;
}
void CommandSession::internalDeviceAvailableCallback(QString deviceId, AMDeviceRef device)
{
if (deviceId != this->deviceId && !this->deviceId.isEmpty())