-
Notifications
You must be signed in to change notification settings - Fork 493
Description
Description
When a DRM-protected application (e.g. streaming apps like TOD, Netflix, Disney+) is in the foreground, the MJPEG server's streamScreenshot loop fails continuously with "Cannot take a screenshot within 20000 ms timeout". This causes all other WDA HTTP endpoints (orientation, touch actions, session queries) to become unresponsive or extremely slow, effectively freezing the device for remote control.
Environment
- WebDriverAgent version: latest (built from source)
- iOS version: 18.x / 26.x
- Device: iPhone 15 Pro (also reproducible on other models)
- Xcode version: 16.x
Steps to Reproduce
- Start a WDA session with MJPEG streaming enabled
- Open a DRM-protected streaming app (e.g. Netflix, Disney+, or any app using FairPlay DRM)
- Play any video content
- Try to interact with the device via WDA (tap, swipe, get orientation, etc.)
Expected Behavior
MJPEG screenshot failures should not block other WDA HTTP endpoints. Touch actions, orientation queries, and other commands should continue to work normally even when screenshots cannot be taken.
Actual Behavior
The MJPEG server enters a tight retry loop, logging errors every ~1 second:
Error Domain=com.facebook.WebDriverAgent Code=1 "Cannot take a screenshot within 20000 ms timeout"
This blocks the WDA HTTP server, causing:
GET /session/{id}/orientationrequests to timeout (12s+)POST /session/{id}/actions(touch/swipe) to queue up and execute with massive delay- Device becomes effectively unresponsive for 10-40+ seconds
Root Cause Analysis
In FBMjpegServer.m, the streamScreenshot method uses a serial dispatch queue. When FBScreenshot takeInOriginalResolutionWithScreenID: fails (returns nil), the method immediately schedules the next attempt via scheduleNextScreenshotWithInterval: with the normal frame interval — meaning it retries at full framerate (e.g. 30fps = every ~33ms).
Since iOS blocks screenshot capture for DRM-protected content, every attempt fails, creating a tight loop of failed screenshot calls that saturates the XCTest framework and starves other WDA requests.
Suggested Fix
Add a backoff mechanism when consecutive screenshot failures occur:
if (nil == screenshotData) {
self.consecutiveScreenshotFailures++;
NSUInteger backoffMs = MIN(self.consecutiveScreenshotFailures * 500, 2000);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(backoffMs * NSEC_PER_MSEC)), self.backgroundQueue, ^{
[self streamScreenshot];
});
return;
}
self.consecutiveScreenshotFailures = 0;
This would:
Gradually increase retry delay (500ms → 1s → 1.5s → 2s max)
Free up the XCTest framework to process other requests between retries
Automatically recover to full framerate once screenshots succeed again