github doronz88/pymobiledevice3 v11.24.0

4 hours ago

Highlights

🐛 RemoteXPC services no longer crash on a second request

RemoteXPC gives each side of a connection its own message-id parity: the connecting side's ids are odd, the listener's even. The client numbered its messages 0, 1, 2, 3, so every other request carried an even id, and a device daemon asked to reply to one aborts with Attempted to send non-reply msg on the reply channel. In practice only the first reply-wanting request on a connection was safe.

Requests are now numbered 1, 3, 5. Several reply-wanting requests on one connection work against notification_proxy, restoreserviced, cryptexd, the pasteboard service and the display service.

The workarounds this made unnecessary are gone: device-side restore preflight and pasteboard reads use one connection, and the touch session and RTP capture helpers stop a media stream on the connection that started it.

✨ Typed notification events

receive_notification() on NotificationProxyService and RemoteNotificationProxyService now yields NotificationEvent, a dataclass with command, name and state. It is still the dict the device sent, so existing code that subscripts it, compares it with a dict or serializes it to JSON keeps working.

state is the notification's 64-bit notify_get_state() value, which the secure proxy relays since iOS 27.2.

async with NotificationProxyService(lockdown) as proxy:
    await proxy.notify_register_dispatch("com.apple.springboard.lockstate")
    async for event in proxy.receive_notification():
        print(event.name, event.state)

✨ TimeSyncService: measure the device clock

com.apple.timed.remote answers SNTP requests carried as RemoteXPC messages. TimeSyncService uses it to measure how far the device clock is from the host's, to well under a millisecond. It is a library API (no CLI command), needs an RSD tunnel and was verified on iOS 27.2. The service only answers; it cannot set the device time.

from pymobiledevice3.services.timesync import TimeSyncService

async with TimeSyncService(rsd) as timesync:
    sample = await timesync.measure()
    print(sample.offset, sample.delay)

What's Changed

Full Changelog: v11.23.1...v11.24.0

Don't miss a new pymobiledevice3 release

NewReleases is sending notifications on new releases.