use of org.robovm.libimobiledevice.LibIMobileDeviceException in project robovm by robovm.
the class AppLauncher method installInternal.
private void installInternal() throws Exception {
try (LockdowndClient lockdowndClient = new LockdowndClient(device, getClass().getSimpleName(), true)) {
final LibIMobileDeviceException[] ex = new LibIMobileDeviceException[1];
final CountDownLatch countDownLatch = new CountDownLatch(1);
LockdowndServiceDescriptor instproxyService = lockdowndClient.startService(InstallationProxyClient.SERVICE_NAME);
try (InstallationProxyClient instClient = new InstallationProxyClient(device, instproxyService)) {
instClient.upgrade("/PublicStaging/" + localAppPath.getName(), new Options().packageType(localAppPath.isDirectory() ? PackageType.Developer : null), new StatusCallback() {
@Override
public void progress(String status, int percentComplete) {
if (installStatusCallback != null) {
installStatusCallback.progress(status, percentComplete);
} else {
log("[%3d%%] %s", 50 + percentComplete / 2, status);
}
}
@Override
public void success() {
try {
if (installStatusCallback != null) {
installStatusCallback.success();
} else {
log("[100%%] Installation complete");
}
} finally {
countDownLatch.countDown();
}
}
@Override
public void error(String message) {
try {
ex[0] = new LibIMobileDeviceException(message);
if (installStatusCallback != null) {
installStatusCallback.error(message);
} else {
log("Error: %s", message);
}
} finally {
countDownLatch.countDown();
}
}
});
countDownLatch.await();
}
if (ex[0] != null) {
throw ex[0];
}
}
}
use of org.robovm.libimobiledevice.LibIMobileDeviceException in project robovm by robovm.
the class AppLauncher method launchInternal.
private int launchInternal() throws Exception {
install();
int lockedRetriesLeft = launchOnLockedRetries;
while (true) {
IDeviceConnection conn = null;
String appPath = null;
try (LockdowndClient lockdowndClient = new LockdowndClient(device, getClass().getSimpleName(), true)) {
appPath = getAppPath(lockdowndClient, appId);
// E.g. 7.0.2
String productVersion = lockdowndClient.getValue(null, "ProductVersion").toString();
// E.g. 11B508
String buildVersion = lockdowndClient.getValue(null, "BuildVersion").toString();
if (appLauncherCallback != null) {
appLauncherCallback.setAppLaunchInfo(new AppLauncherInfo(device, appPath, productVersion, buildVersion));
}
LockdowndServiceDescriptor debugService = null;
try {
debugService = lockdowndClient.startService(DEBUG_SERVER_SERVICE_NAME);
} catch (LibIMobileDeviceException e) {
if (e.getErrorCode() == LockdowndError.LOCKDOWN_E_INVALID_SERVICE.swigValue()) {
// This happens when the developer image hasn't been mounted.
// Mount and try again.
mountDeveloperImage(lockdowndClient);
debugService = lockdowndClient.startService(DEBUG_SERVER_SERVICE_NAME);
} else {
throw e;
}
}
conn = device.connect(debugService.getPort());
log("Debug server port: " + debugService.getPort());
if (localPort != -1) {
String exe = ((NSDictionary) PropertyListParser.parse(new File(localAppPath, "Info.plist"))).objectForKey("CFBundleExecutable").toString();
log("launchios \"" + new File(localAppPath, exe).getAbsolutePath() + "\" \"" + appPath + "\" " + localPort);
StringBuilder argsString = new StringBuilder();
for (String arg : args) {
if (argsString.length() > 0) {
argsString.append(' ');
}
argsString.append(arg);
}
log("process launch -- " + argsString);
}
}
if (lockedRetriesLeft == launchOnLockedRetries) {
// First try
log("Remote app path: " + appPath);
log("Launching app...");
} else {
log("Launching app (retry %d of %d)...", (launchOnLockedRetries - lockedRetriesLeft), launchOnLockedRetries);
}
try {
// otherwise perform port forwarding and stdout piping
if (localPort == -1) {
return pipeStdOut(conn, appPath);
} else {
return forward(conn, appPath);
}
} catch (RuntimeException e) {
if (!e.getMessage().contains("Locked") || lockedRetriesLeft == 0) {
throw e;
}
lockedRetriesLeft--;
log("Device locked. Retrying launch in %d seconds...", secondsBetweenLaunchOnLockedRetries);
Thread.sleep(secondsBetweenLaunchOnLockedRetries * 1000);
} finally {
conn.dispose();
}
}
}
use of org.robovm.libimobiledevice.LibIMobileDeviceException in project robovm by robovm.
the class AppLauncher method forward.
private int forward(IDeviceConnection conn, String appPath) throws Exception {
boolean wasInterrupted = false;
Socket clientSocket = null;
try (ServerSocket serverSocket = new ServerSocket(localPort)) {
serverSocket.setReuseAddress(true);
log("Waiting for GDB remote connection at http://127.0.0.1:" + localPort);
clientSocket = serverSocket.accept();
clientSocket.setTcpNoDelay(true);
log("GDB remote client connected");
}
try (FileOutputStream fileOut = new FileOutputStream("/tmp/dbgout")) {
final InputStream in = clientSocket.getInputStream();
final OutputStream out = clientSocket.getOutputStream();
byte[] buffer = new byte[10 * 4096];
GdbRemoteParser lldbParser = new GdbRemoteParser();
GdbRemoteParser debugServerParser = new GdbRemoteParser();
boolean nextPacketIsData = false;
while (true) {
try {
// command here, but we don't really care
if (in.available() > 0) {
int readBytes = in.read(buffer);
int sent = 0;
while (sent != readBytes) {
sent += conn.send(buffer, sent, readBytes - sent);
}
List<byte[]> messages = lldbParser.parse(buffer, 0, readBytes);
debugForward(fileOut, "lldb->debugserver: ", messages);
for (byte[] m : messages) {
if (m[1] == 'x') {
nextPacketIsData = true;
break;
}
}
}
// check if we've been interrupted
if (killed || Thread.currentThread().isInterrupted()) {
killed = true;
throw new InterruptedIOException();
}
// for 10 milliseconds
try {
int readBytes = conn.receive(buffer, 0, buffer.length, 1);
if (readBytes > 0) {
out.write(buffer, 0, readBytes);
out.flush();
List<byte[]> messages = debugServerParser.parse(buffer, 0, readBytes);
for (byte[] message : messages) {
if (message[1] == 'W') {
// The app exited. The number following W is the exit code.
int exitCode = Integer.parseInt(new String(message, 2, message.length - 2 - 3, "ASCII"), 16);
return exitCode;
} else if (message[1] == 'O') {
// Console output encoded as hex.
if (!nextPacketIsData) {
byte[] data = fromHex(message, 2, message.length - 2 - 3);
if (appLauncherCallback != null) {
data = appLauncherCallback.filterOutput(data);
}
stdout.write(data);
} else {
nextPacketIsData = false;
}
}
}
debugForward(fileOut, "debugserver->lldb: ", messages);
}
} catch (Exception e) {
// means the device might be locked or crashed.
if (e instanceof LibIMobileDeviceException) {
throw new InterruptedIOException(e.getMessage());
}
}
} catch (InterruptedIOException e) {
// Remember whether we were interrupted. kill() clears
// the thread's interrupted state and we want to reset it
// when we exit.
wasInterrupted = Thread.currentThread().isInterrupted();
kill(conn);
}
}
} finally {
if (clientSocket != null) {
clientSocket.close();
}
if (wasInterrupted) {
Thread.currentThread().interrupt();
}
}
}
Aggregations