Skip to content

Commit

Permalink
* libmobiledevice maintenance: waiting for device and error handling (#…
Browse files Browse the repository at this point in the history
…726)

reason: libmobiledevice was failing on every situation then: device is not connected, blocked or pairing not complete. considering build process and deployment might take minutes its sad to fail just due to blocked device.
changes: mitigation for these cases done by allowing 20 seconds for user to act to solve the situation:
- if no device connected -- waiting for device
- if device is locked -- waiting for unlock
- if pairing in progress -- waiting to complete

other changes:
- changed logic for picking dev image -- all version are parsed and picked exact or lower (fix for #517)
- idea plugin: install was moved inside Run process. As before it was happening on UI thread and entire Idea was frozen (there was no update or locked device retries message);
- using Java9 language level for RoboVM compiler/plugins.
- amount for TODO added to point for code fragments that to be refactored (like Launchers, junit client depends on old structure)
  • Loading branch information
dkimitsa committed May 4, 2023
1 parent 705105b commit 2f78109
Show file tree
Hide file tree
Showing 16 changed files with 648 additions and 349 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ ResolvedLocations resolve() {
}

if (xcFrameworks != null && !xcFrameworks.isEmpty()) {
// there is xcframeworks, expand them
// there are xcframeworks, expand them
handleXCFrameworks();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,20 @@ public byte[] filterOutput(byte[] data) {
@Override
public void connect() {
try {
// FIXME: waiting for app to be deployed and prepared, its should not use TARGET_WAIT_TIMEOUT time
// and it has to be moved to pre-launch sequence
long ts = System.currentTimeMillis();
while (launchInfo == null) {
if (System.currentTimeMillis() - ts > DebuggerConfig.TARGET_DEPLOY_TIMEOUT)
throw new DebuggerException("Timeout while waiting app is deployed");
Thread.sleep(200);
}

// waiting for target to start and hooks are available
ts = System.currentTimeMillis();
while (hooksPort == null) {
if (System.currentTimeMillis() - ts > DebuggerConfig.TARGET_WAIT_TIMEOUT)
throw new DebuggerException("Timeout while waiting simulator port file");
throw new DebuggerException("Timeout while waiting app is responding on device");
Thread.sleep(200);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ public AppLauncherProcess(Logger log, AppLauncher launcher, LaunchParameters lau

@Override
public Process execAsync() throws IOException {
launcher.install();
this.launcherThread = new Thread("AppLauncherThread-" + threadCounter.getAndIncrement()) {
@Override
public void run() {
try {
// install and launch
exitCode = launcher.launch();
} catch (Throwable t) {
log.error("AppLauncher failed with an exception:", t.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public class IOSTarget extends AbstractTarget {
private File entitlementsPList;
private SigningIdentity signIdentity;
private ProvisioningProfile provisioningProfile;
@Deprecated
private IDevice device;
private File partialPListDir;

Expand Down Expand Up @@ -175,21 +176,24 @@ private Launcher createIOSDevLauncher(LaunchParameters launchParameters)
throws IOException {

IOSDeviceLaunchParameters deviceLaunchParameters = (IOSDeviceLaunchParameters) launchParameters;
String deviceId = deviceLaunchParameters.getDeviceId();
String deviceUdid = deviceLaunchParameters.getDeviceId();
int forwardPort = deviceLaunchParameters.getForwardPort();
AppLauncherCallback callback = deviceLaunchParameters.getAppPathCallback();
if (deviceId == null || deviceId.isEmpty()) {
String[] udids = IDevice.listUdids();
if (udids.length == 0) {
throw new RuntimeException("No devices connected");

// TODO: FIXME: proxy AppLauncherCallback here: device to be captured as it is being used in junit client
// its a subject for future rework
AppLauncherCallback callback = deviceLaunchParameters.getAppPathCallback() != null ? new AppLauncherCallback() {
final AppLauncherCallback delegate = deviceLaunchParameters.getAppPathCallback();
@Override
public void setAppLaunchInfo(AppLauncherInfo info) {
device = info.getDevice();
delegate.setAppLaunchInfo(info);
}
if (udids.length > 1) {
config.getLogger().warn("More than 1 device connected (%s). "
+ "Using %s.", Arrays.asList(udids), udids[0]);

@Override
public byte[] filterOutput(byte[] data) {
return delegate.filterOutput(data);
}
deviceId = udids[0];
}
device = new IDevice(deviceId);
} : null;

OutputStream out = null;
if (launchParameters.getStdoutFifo() != null) {
Expand All @@ -205,7 +209,7 @@ private Launcher createIOSDevLauncher(LaunchParameters launchParameters)
//Fix for #71, see http://stackoverflow.com/questions/37800790/hide-strange-unwanted-xcode-8-logs
env.put("OS_ACTIVITY_DT_MODE", "");

AppLauncher launcher = new AppLauncher(device, getAppDir()) {
AppLauncher launcher = new AppLauncher(deviceUdid, getAppDir()) {
protected void log(String s, Object... args) {
config.getLogger().info(s, args);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
*/
public class LockdowndClient implements AutoCloseable {
protected LockdowndClientRef ref;
private IDevice device;

LockdowndClient(LockdowndClientRef ref) {
this.ref = ref;
Expand All @@ -58,6 +59,7 @@ public LockdowndClient(IDevice device, String label, boolean handshake) {
LibIMobileDevice.lockdownd_client_new_with_handshake(device.getRef(), refOut, label) :
LibIMobileDevice.lockdownd_client_new(device.getRef(), refOut, label));
this.ref = refOut.getValue();
this.device = device;
} finally {
refOut.delete();
}
Expand All @@ -67,7 +69,11 @@ protected LockdowndClientRef getRef() {
checkDisposed();
return ref;
}


public IDevice getDevice() {
return device;
}

/**
* Requests to start a service.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.nio.file.Files;
import java.util.Arrays;

import com.dd.plist.NSString;
import org.robovm.libimobiledevice.binding.LibIMobileDevice;
import org.robovm.libimobiledevice.binding.LibIMobileDeviceConstants;
import org.robovm.libimobiledevice.binding.LockdowndServiceDescriptorStruct;
Expand All @@ -34,6 +35,9 @@
import com.dd.plist.NSDictionary;
import com.dd.plist.NSObject;

import static org.robovm.libimobiledevice.binding.MobileImageMounterError.MOBILE_IMAGE_MOUNTER_E_DEVICE_LOCKED;
import static org.robovm.libimobiledevice.binding.MobileImageMounterError.MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR;

/**
* Mounts developer/debug disk images on the device.
*/
Expand Down Expand Up @@ -153,7 +157,18 @@ public NSDictionary lookupImage(String imageType) throws IOException {
try {
checkResult(LibIMobileDevice.mobile_image_mounter_lookup_image(getRef(), imageType, plistOut));
PlistRef plist = plistOut.getValue();
return (NSDictionary) PlistUtil.toJavaPlist(plist);
NSDictionary dict = (NSDictionary) PlistUtil.toJavaPlist(plist);
// TODO: mobile_image_mounter_lookup_image doesn't check plist for possible error, this might
// happen when device is locked
NSString possibleError = dict != null ? (NSString) dict.objectForKey("Error") : null;
if (possibleError != null) {
if ("DeviceLocked".equals(possibleError.toString()))
throw new LibIMobileDeviceException(MOBILE_IMAGE_MOUNTER_E_DEVICE_LOCKED.swigValue(),
MOBILE_IMAGE_MOUNTER_E_DEVICE_LOCKED.name());
throw new LibIMobileDeviceException(MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR.swigValue(),
MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR.name());
}
return dict;
} finally {
plistOut.delete();
}
Expand Down
Loading

0 comments on commit 2f78109

Please sign in to comment.