pymobiledevice3 4.14.6__py3-none-any.whl → 7.0.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. misc/plist_sniffer.py +15 -15
  2. misc/remotexpc_sniffer.py +29 -28
  3. misc/understanding_idevice_protocol_layers.md +15 -10
  4. pymobiledevice3/__main__.py +317 -127
  5. pymobiledevice3/_version.py +22 -4
  6. pymobiledevice3/bonjour.py +358 -113
  7. pymobiledevice3/ca.py +253 -16
  8. pymobiledevice3/cli/activation.py +31 -23
  9. pymobiledevice3/cli/afc.py +49 -40
  10. pymobiledevice3/cli/amfi.py +16 -21
  11. pymobiledevice3/cli/apps.py +87 -42
  12. pymobiledevice3/cli/backup.py +160 -90
  13. pymobiledevice3/cli/bonjour.py +44 -40
  14. pymobiledevice3/cli/cli_common.py +204 -198
  15. pymobiledevice3/cli/companion_proxy.py +14 -14
  16. pymobiledevice3/cli/crash.py +105 -56
  17. pymobiledevice3/cli/developer/__init__.py +62 -0
  18. pymobiledevice3/cli/developer/accessibility/__init__.py +65 -0
  19. pymobiledevice3/cli/developer/accessibility/settings.py +43 -0
  20. pymobiledevice3/cli/developer/arbitration.py +50 -0
  21. pymobiledevice3/cli/developer/condition.py +33 -0
  22. pymobiledevice3/cli/developer/core_device.py +294 -0
  23. pymobiledevice3/cli/developer/debugserver.py +244 -0
  24. pymobiledevice3/cli/developer/dvt/__init__.py +438 -0
  25. pymobiledevice3/cli/developer/dvt/core_profile_session.py +295 -0
  26. pymobiledevice3/cli/developer/dvt/simulate_location.py +56 -0
  27. pymobiledevice3/cli/developer/dvt/sysmon/__init__.py +69 -0
  28. pymobiledevice3/cli/developer/dvt/sysmon/process.py +188 -0
  29. pymobiledevice3/cli/developer/fetch_symbols.py +108 -0
  30. pymobiledevice3/cli/developer/simulate_location.py +51 -0
  31. pymobiledevice3/cli/diagnostics/__init__.py +75 -0
  32. pymobiledevice3/cli/diagnostics/battery.py +47 -0
  33. pymobiledevice3/cli/idam.py +42 -0
  34. pymobiledevice3/cli/lockdown.py +108 -103
  35. pymobiledevice3/cli/mounter.py +158 -99
  36. pymobiledevice3/cli/notification.py +38 -26
  37. pymobiledevice3/cli/pcap.py +45 -24
  38. pymobiledevice3/cli/power_assertion.py +18 -17
  39. pymobiledevice3/cli/processes.py +17 -23
  40. pymobiledevice3/cli/profile.py +165 -109
  41. pymobiledevice3/cli/provision.py +35 -34
  42. pymobiledevice3/cli/remote.py +217 -129
  43. pymobiledevice3/cli/restore.py +159 -143
  44. pymobiledevice3/cli/springboard.py +63 -53
  45. pymobiledevice3/cli/syslog.py +193 -86
  46. pymobiledevice3/cli/usbmux.py +73 -33
  47. pymobiledevice3/cli/version.py +5 -7
  48. pymobiledevice3/cli/webinspector.py +376 -214
  49. pymobiledevice3/common.py +3 -1
  50. pymobiledevice3/exceptions.py +182 -58
  51. pymobiledevice3/irecv.py +52 -53
  52. pymobiledevice3/irecv_devices.py +1489 -464
  53. pymobiledevice3/lockdown.py +473 -275
  54. pymobiledevice3/lockdown_service_provider.py +15 -8
  55. pymobiledevice3/osu/os_utils.py +27 -9
  56. pymobiledevice3/osu/posix_util.py +34 -15
  57. pymobiledevice3/osu/win_util.py +14 -8
  58. pymobiledevice3/pair_records.py +102 -21
  59. pymobiledevice3/remote/common.py +8 -4
  60. pymobiledevice3/remote/core_device/app_service.py +94 -67
  61. pymobiledevice3/remote/core_device/core_device_service.py +17 -14
  62. pymobiledevice3/remote/core_device/device_info.py +5 -5
  63. pymobiledevice3/remote/core_device/diagnostics_service.py +19 -4
  64. pymobiledevice3/remote/core_device/file_service.py +53 -23
  65. pymobiledevice3/remote/remote_service_discovery.py +79 -45
  66. pymobiledevice3/remote/remotexpc.py +73 -44
  67. pymobiledevice3/remote/tunnel_service.py +442 -317
  68. pymobiledevice3/remote/utils.py +14 -13
  69. pymobiledevice3/remote/xpc_message.py +145 -125
  70. pymobiledevice3/resources/dsc_uuid_map.py +19 -19
  71. pymobiledevice3/resources/firmware_notifications.py +20 -16
  72. pymobiledevice3/resources/notifications.txt +144 -0
  73. pymobiledevice3/restore/asr.py +27 -27
  74. pymobiledevice3/restore/base_restore.py +110 -21
  75. pymobiledevice3/restore/consts.py +87 -66
  76. pymobiledevice3/restore/device.py +59 -12
  77. pymobiledevice3/restore/fdr.py +46 -48
  78. pymobiledevice3/restore/ftab.py +19 -19
  79. pymobiledevice3/restore/img4.py +163 -0
  80. pymobiledevice3/restore/mbn.py +587 -0
  81. pymobiledevice3/restore/recovery.py +151 -151
  82. pymobiledevice3/restore/restore.py +562 -544
  83. pymobiledevice3/restore/restore_options.py +131 -110
  84. pymobiledevice3/restore/restored_client.py +51 -31
  85. pymobiledevice3/restore/tss.py +385 -267
  86. pymobiledevice3/service_connection.py +252 -59
  87. pymobiledevice3/services/accessibilityaudit.py +202 -120
  88. pymobiledevice3/services/afc.py +962 -365
  89. pymobiledevice3/services/amfi.py +24 -30
  90. pymobiledevice3/services/companion.py +23 -19
  91. pymobiledevice3/services/crash_reports.py +71 -47
  92. pymobiledevice3/services/debugserver_applist.py +3 -3
  93. pymobiledevice3/services/device_arbitration.py +8 -8
  94. pymobiledevice3/services/device_link.py +101 -79
  95. pymobiledevice3/services/diagnostics.py +973 -967
  96. pymobiledevice3/services/dtfetchsymbols.py +8 -8
  97. pymobiledevice3/services/dvt/dvt_secure_socket_proxy.py +4 -4
  98. pymobiledevice3/services/dvt/dvt_testmanaged_proxy.py +4 -4
  99. pymobiledevice3/services/dvt/instruments/activity_trace_tap.py +85 -74
  100. pymobiledevice3/services/dvt/instruments/application_listing.py +2 -3
  101. pymobiledevice3/services/dvt/instruments/condition_inducer.py +7 -6
  102. pymobiledevice3/services/dvt/instruments/core_profile_session_tap.py +466 -384
  103. pymobiledevice3/services/dvt/instruments/device_info.py +20 -11
  104. pymobiledevice3/services/dvt/instruments/energy_monitor.py +1 -1
  105. pymobiledevice3/services/dvt/instruments/graphics.py +1 -1
  106. pymobiledevice3/services/dvt/instruments/location_simulation.py +1 -1
  107. pymobiledevice3/services/dvt/instruments/location_simulation_base.py +10 -10
  108. pymobiledevice3/services/dvt/instruments/network_monitor.py +17 -17
  109. pymobiledevice3/services/dvt/instruments/notifications.py +1 -1
  110. pymobiledevice3/services/dvt/instruments/process_control.py +35 -10
  111. pymobiledevice3/services/dvt/instruments/screenshot.py +2 -2
  112. pymobiledevice3/services/dvt/instruments/sysmontap.py +15 -15
  113. pymobiledevice3/services/dvt/testmanaged/xcuitest.py +42 -52
  114. pymobiledevice3/services/file_relay.py +10 -10
  115. pymobiledevice3/services/heartbeat.py +9 -8
  116. pymobiledevice3/services/house_arrest.py +16 -15
  117. pymobiledevice3/services/idam.py +20 -0
  118. pymobiledevice3/services/installation_proxy.py +173 -81
  119. pymobiledevice3/services/lockdown_service.py +20 -10
  120. pymobiledevice3/services/misagent.py +22 -19
  121. pymobiledevice3/services/mobile_activation.py +147 -64
  122. pymobiledevice3/services/mobile_config.py +331 -294
  123. pymobiledevice3/services/mobile_image_mounter.py +141 -113
  124. pymobiledevice3/services/mobilebackup2.py +203 -145
  125. pymobiledevice3/services/notification_proxy.py +11 -11
  126. pymobiledevice3/services/os_trace.py +134 -74
  127. pymobiledevice3/services/pcapd.py +314 -302
  128. pymobiledevice3/services/power_assertion.py +10 -9
  129. pymobiledevice3/services/preboard.py +4 -4
  130. pymobiledevice3/services/remote_fetch_symbols.py +21 -14
  131. pymobiledevice3/services/remote_server.py +176 -146
  132. pymobiledevice3/services/restore_service.py +16 -16
  133. pymobiledevice3/services/screenshot.py +15 -12
  134. pymobiledevice3/services/simulate_location.py +7 -7
  135. pymobiledevice3/services/springboard.py +15 -15
  136. pymobiledevice3/services/syslog.py +5 -5
  137. pymobiledevice3/services/web_protocol/alert.py +11 -11
  138. pymobiledevice3/services/web_protocol/automation_session.py +251 -239
  139. pymobiledevice3/services/web_protocol/cdp_screencast.py +46 -37
  140. pymobiledevice3/services/web_protocol/cdp_server.py +19 -19
  141. pymobiledevice3/services/web_protocol/cdp_target.py +411 -373
  142. pymobiledevice3/services/web_protocol/driver.py +114 -111
  143. pymobiledevice3/services/web_protocol/element.py +124 -111
  144. pymobiledevice3/services/web_protocol/inspector_session.py +106 -102
  145. pymobiledevice3/services/web_protocol/selenium_api.py +49 -49
  146. pymobiledevice3/services/web_protocol/session_protocol.py +18 -12
  147. pymobiledevice3/services/web_protocol/switch_to.py +30 -27
  148. pymobiledevice3/services/webinspector.py +189 -155
  149. pymobiledevice3/tcp_forwarder.py +87 -69
  150. pymobiledevice3/tunneld/__init__.py +0 -0
  151. pymobiledevice3/tunneld/api.py +63 -0
  152. pymobiledevice3/tunneld/server.py +603 -0
  153. pymobiledevice3/usbmux.py +198 -147
  154. pymobiledevice3/utils.py +14 -11
  155. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/METADATA +55 -28
  156. pymobiledevice3-7.0.6.dist-info/RECORD +188 -0
  157. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/WHEEL +1 -1
  158. pymobiledevice3/cli/developer.py +0 -1215
  159. pymobiledevice3/cli/diagnostics.py +0 -99
  160. pymobiledevice3/tunneld.py +0 -524
  161. pymobiledevice3-4.14.6.dist-info/RECORD +0 -168
  162. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/entry_points.txt +0 -0
  163. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info/licenses}/LICENSE +0 -0
  164. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/top_level.txt +0 -0
@@ -1,119 +1,130 @@
1
1
  # extracted from ac2
2
2
  import logging
3
3
  import uuid
4
+ from typing import Optional
4
5
 
5
6
  from ipsw_parser.build_identity import BuildIdentity
6
7
 
7
8
  logger = logging.getLogger(__name__)
8
9
 
9
10
  SUPPORTED_DATA_TYPES = {
10
- 'BasebandBootData': False,
11
- 'BasebandData': False,
12
- 'BasebandStackData': False,
13
- 'BasebandUpdaterOutputData': False,
14
- 'BootabilityBundle': False,
15
- 'BuildIdentityDict': False,
16
- 'BuildIdentityDictV2': False,
17
- 'DataType': False,
18
- 'DiagData': False,
19
- 'EANData': False,
20
- 'FDRMemoryCommit': False,
21
- 'FDRTrustData': False,
22
- 'FUDData': False,
23
- 'FileData': False,
24
- 'FileDataDone': False,
25
- 'FirmwareUpdaterData': False,
26
- 'GrapeFWData': False,
27
- 'HPMFWData': False,
28
- 'HostSystemTime': True,
29
- 'KernelCache': False,
30
- 'NORData': False,
31
- 'NitrogenFWData': True,
32
- 'OpalFWData': False,
33
- 'OverlayRootDataCount': False,
34
- 'OverlayRootDataForKey': True,
35
- 'PeppyFWData': True,
36
- 'PersonalizedBootObjectV3': False,
37
- 'PersonalizedData': True,
38
- 'ProvisioningData': False,
39
- 'RamdiskFWData': True,
40
- 'RecoveryOSASRImage': True,
41
- 'RecoveryOSAppleLogo': True,
42
- 'RecoveryOSDeviceTree': True,
43
- 'RecoveryOSFileAssetImage': True,
44
- 'RecoveryOSIBEC': True,
45
- 'RecoveryOSIBootFWFilesImages': True,
46
- 'RecoveryOSImage': True,
47
- 'RecoveryOSKernelCache': True,
48
- 'RecoveryOSLocalPolicy': True,
49
- 'RecoveryOSOverlayRootDataCount': False,
50
- 'RecoveryOSRootTicketData': True,
51
- 'RecoveryOSStaticTrustCache': True,
52
- 'RecoveryOSVersionData': True,
53
- 'RootData': False,
54
- 'RootTicket': False,
55
- 'S3EOverride': False,
56
- 'SourceBootObjectV3': False,
57
- 'SourceBootObjectV4': False,
58
- 'SsoServiceTicket': False,
59
- 'StockholmPostflight': False,
60
- 'SystemImageCanonicalMetadata': False,
61
- 'SystemImageData': False,
62
- 'SystemImageRootHash': False,
63
- 'USBCFWData': False,
64
- 'USBCOverride': False,
65
- 'FirmwareUpdaterPreflight': True,
66
- 'ReceiptManifest': True,
67
- 'FirmwareUpdaterDataV2': False,
68
- 'RestoreLocalPolicy': True,
69
- 'AuthInstallCACert': True,
70
- 'OverlayRootDataForKeyIndex': True,
71
-
11
+ "BasebandBootData": False,
12
+ "BasebandData": False,
13
+ "BasebandStackData": False,
14
+ "BasebandUpdaterOutputData": False,
15
+ "BootabilityBundle": False,
16
+ "BuildIdentityDict": False,
17
+ "BuildIdentityDictV2": False,
18
+ "DataType": False,
19
+ "DiagData": False,
20
+ "EANData": False,
21
+ "FDRMemoryCommit": False,
22
+ "FDRTrustData": False,
23
+ "FUDData": False,
24
+ "FileData": False,
25
+ "FileDataDone": False,
26
+ "FirmwareUpdaterData": False,
27
+ "GrapeFWData": False,
28
+ "HPMFWData": False,
29
+ "HostSystemTime": True,
30
+ "KernelCache": False,
31
+ "NORData": False,
32
+ "NitrogenFWData": True,
33
+ "OpalFWData": False,
34
+ "OverlayRootDataCount": False,
35
+ "OverlayRootDataForKey": True,
36
+ "PeppyFWData": True,
37
+ "PersonalizedBootObjectV3": False,
38
+ "PersonalizedData": True,
39
+ "ProvisioningData": False,
40
+ "RamdiskFWData": True,
41
+ "RecoveryOSASRImage": True,
42
+ "RecoveryOSAppleLogo": True,
43
+ "RecoveryOSDeviceTree": True,
44
+ "RecoveryOSFileAssetImage": True,
45
+ "RecoveryOSIBEC": True,
46
+ "RecoveryOSIBootFWFilesImages": True,
47
+ "RecoveryOSImage": True,
48
+ "RecoveryOSKernelCache": True,
49
+ "RecoveryOSLocalPolicy": True,
50
+ "RecoveryOSOverlayRootDataCount": False,
51
+ "RecoveryOSRootTicketData": True,
52
+ "RecoveryOSStaticTrustCache": True,
53
+ "RecoveryOSVersionData": True,
54
+ "RootData": False,
55
+ "RootTicket": False,
56
+ "S3EOverride": False,
57
+ "SourceBootObjectV3": False,
58
+ "SourceBootObjectV4": False,
59
+ "SsoServiceTicket": False,
60
+ "StockholmPostflight": False,
61
+ "SystemImageCanonicalMetadata": False,
62
+ "SystemImageData": False,
63
+ "SystemImageRootHash": False,
64
+ "USBCFWData": False,
65
+ "USBCOverride": False,
66
+ "FirmwareUpdaterPreflight": True,
67
+ "ReceiptManifest": True,
68
+ "FirmwareUpdaterDataV2": False,
69
+ "RestoreLocalPolicy": True,
70
+ "AuthInstallCACert": True,
71
+ "OverlayRootDataForKeyIndex": True,
72
72
  # Added in iOS 18.0 beta1
73
- 'FirmwareUpdaterDataV3': True,
74
- 'MessageUseStreamedImageFile': True,
75
- 'UpdateVolumeOverlayRootDataCount': True,
76
- 'URLAsset': True,
73
+ "FirmwareUpdaterDataV3": True,
74
+ "MessageUseStreamedImageFile": True,
75
+ "UpdateVolumeOverlayRootDataCount": True,
76
+ "URLAsset": True,
77
77
  }
78
78
 
79
79
  # extracted from ac2
80
80
  SUPPORTED_MESSAGE_TYPES = {
81
- 'BBUpdateStatusMsg': False,
82
- 'CheckpointMsg': True,
83
- 'DataRequestMsg': False,
84
- 'FDRSubmit': True,
85
- 'MsgType': False,
86
- 'PreviousRestoreLogMsg': False,
87
- 'ProgressMsg': False,
88
- 'ProvisioningAck': False,
89
- 'ProvisioningInfo': False,
90
- 'ProvisioningStatusMsg': False,
91
- 'ReceivedFinalStatusMsg': False,
92
- 'RestoredCrash': True,
93
- 'StatusMsg': False,
94
-
81
+ "BBUpdateStatusMsg": False,
82
+ "CheckpointMsg": True,
83
+ "CrashLog": True,
84
+ "DataRequestMsg": False,
85
+ "FDRSubmit": True,
86
+ "MsgType": False,
87
+ "PreviousRestoreLogMsg": False,
88
+ "ProgressMsg": False,
89
+ "ProvisioningAck": False,
90
+ "ProvisioningInfo": False,
91
+ "ProvisioningStatusMsg": False,
92
+ "ReceivedFinalStatusMsg": False,
93
+ "RestoredCrash": True,
94
+ "StatusMsg": False,
95
95
  # Added in iOS 18.0 beta1
96
- 'AsyncDataRequestMsg': True,
97
- 'AsyncWait': True,
98
- 'RestoreAttestation': True,
96
+ "AsyncDataRequestMsg": True,
97
+ "AsyncWait": True,
98
+ "RestoreAttestation": True,
99
99
  }
100
100
 
101
101
 
102
102
  class RestoreOptions:
103
-
104
- def __init__(self, preflight_info=None, sep=None, macos_variant=None, build_identity: BuildIdentity = None,
105
- restore_boot_args=None, spp=None, restore_behavior: str = None, msp=None):
103
+ def __init__(
104
+ self,
105
+ firmware_preflight_info=None,
106
+ sep=None,
107
+ macos_variant=None,
108
+ build_identity: BuildIdentity = None,
109
+ restore_boot_args=None,
110
+ spp=None,
111
+ restore_behavior: Optional[str] = None,
112
+ msp=None,
113
+ ):
106
114
  self.AutoBootDelay = 0
107
115
 
108
- if preflight_info is not None:
109
- bbus = dict(preflight_info)
110
- bbus.pop('FusingStatus')
111
- bbus.pop('PkHash')
112
- self.BBUpdaterState = bbus
116
+ try:
117
+ if firmware_preflight_info is not None:
118
+ bbus = dict(firmware_preflight_info)
119
+ bbus.pop("FusingStatus")
120
+ bbus.pop("PkHash")
121
+ self.BBUpdaterState = bbus
113
122
 
114
- nonce = preflight_info.get('Nonce')
115
- if nonce is not None:
116
- self.BasebandNonce = nonce
123
+ nonce = firmware_preflight_info.get("Nonce")
124
+ if nonce is not None:
125
+ self.BasebandNonce = nonce
126
+ except KeyError as e:
127
+ logger.warning(f"Skipping addition of firmware_preflight_info due to: {e}")
117
128
 
118
129
  self.SupportedDataTypes = SUPPORTED_DATA_TYPES
119
130
  self.SupportedMessageTypes = SUPPORTED_MESSAGE_TYPES
@@ -155,33 +166,33 @@ class RestoreOptions:
155
166
  if msp:
156
167
  self.SystemPartitionSize = msp
157
168
  else:
158
- self.BootImageType = 'UserOrInternal'
159
- self.DFUFileType = 'RELEASE'
169
+ self.BootImageType = "UserOrInternal"
170
+ self.DFUFileType = "RELEASE"
160
171
  self.DataImage = False
161
- self.FirmwareDirectory = '.'
172
+ self.FirmwareDirectory = "."
162
173
  self.FlashNOR = True
163
- self.KernelCacheType = 'Release'
164
- self.NORImageType = 'production'
165
- self.RestoreBundlePath = '/tmp/Per2.tmp'
166
- self.SystemImageType = 'User'
174
+ self.KernelCacheType = "Release"
175
+ self.NORImageType = "production"
176
+ self.RestoreBundlePath = "/tmp/Per2.tmp"
177
+ self.SystemImageType = "User"
167
178
  self.UpdateBaseband = False
168
179
 
169
180
  # Added for iOS 18.0 beta1
170
181
  self.HostHasFixFor99053849 = True
171
- self.SystemImageFormat = 'AEAWrappedDiskImage'
182
+ self.SystemImageFormat = "AEAWrappedDiskImage"
172
183
  self.WaitForDeviceConnectionToFinishStateMachine = False
173
184
  self.SupportedAsyncDataTypes = {
174
- 'BasebandData': False,
175
- 'RecoveryOSASRImage': False,
176
- 'StreamedImageDecryptionKey': False,
177
- 'SystemImageData': False,
178
- 'URLAsset': True
185
+ "BasebandData": False,
186
+ "RecoveryOSASRImage": False,
187
+ "StreamedImageDecryptionKey": False,
188
+ "SystemImageData": False,
189
+ "URLAsset": True,
179
190
  }
180
191
 
181
192
  if sep is not None:
182
- required_capacity = sep.get('RequiredCapacity')
193
+ required_capacity = sep.get("RequiredCapacity")
183
194
  if required_capacity:
184
- logger.debug(f'TZ0RequiredCapacity: {required_capacity}')
195
+ logger.debug(f"TZ0RequiredCapacity: {required_capacity}")
185
196
  self.TZ0RequiredCapacity = required_capacity
186
197
 
187
198
  self.PersonalizedDuringPreflight = True
@@ -197,7 +208,17 @@ class RestoreOptions:
197
208
  if spp:
198
209
  spp = dict(spp)
199
210
  else:
200
- spp = {'128': 1280, '16': 160, '32': 320, '64': 640, '8': 80}
211
+ spp = {
212
+ "1024": 1280,
213
+ "128": 1280,
214
+ "16": 160,
215
+ "256": 1280,
216
+ "32": 320,
217
+ "512": 1280,
218
+ "64": 640,
219
+ "768": 1280,
220
+ "8": 80,
221
+ }
201
222
  self.SystemPartitionPadding = spp
202
223
 
203
224
  def to_dict(self):
@@ -1,34 +1,62 @@
1
1
  import logging
2
- from functools import cached_property
3
2
  from typing import Any, Optional
4
3
 
5
4
  from pymobiledevice3 import usbmux
6
5
  from pymobiledevice3.exceptions import ConnectionFailedError, NoDeviceConnectedError
6
+ from pymobiledevice3.lockdown import DEFAULT_LABEL
7
7
  from pymobiledevice3.restore.restore_options import RestoreOptions
8
8
  from pymobiledevice3.service_connection import ServiceConnection
9
+ from pymobiledevice3.usbmux import select_devices_by_connection_type
10
+
11
+ logger = logging.getLogger(__name__)
9
12
 
10
13
 
11
14
  class RestoredClient:
12
- DEFAULT_CLIENT_NAME = 'pyMobileDevice'
15
+ DEFAULT_CLIENT_NAME = "pymobiledevice3"
13
16
  SERVICE_PORT = 62078
14
17
 
15
- def __init__(self, udid: Optional[str] = None) -> None:
16
- self.logger = logging.getLogger(__name__)
18
+ @classmethod
19
+ async def create(cls, ecid: str) -> "RestoredClient":
20
+ for mux_device in select_devices_by_connection_type("USB"):
21
+ logger.debug(f"Iterating: {mux_device}")
22
+ service = ServiceConnection.create_using_usbmux(
23
+ mux_device.serial, cls.SERVICE_PORT, connection_type=mux_device.connection_type
24
+ )
25
+ await service.aio_start()
26
+
27
+ query_type = await service.aio_send_recv_plist({"Request": "QueryType"})
28
+ version = query_type.get("RestoreProtocolVersion")
29
+ logger.debug(f"RestoreProtocolVersion: {version}")
30
+
31
+ if query_type.get("Type") != "com.apple.mobile.restored":
32
+ logger.debug(f"Skipping: {mux_device.serial} as its not a restored device")
33
+ await service.aio_close()
34
+ continue
35
+
36
+ restored_client = cls(mux_device.serial, version, service)
37
+ await restored_client._connect()
38
+
39
+ if restored_client.ecid != ecid:
40
+ logger.debug(
41
+ f"Skipping: {restored_client.ecid} as its not the right ECID ({restored_client.ecid} "
42
+ f"instead of {ecid})"
43
+ )
44
+ await service.aio_close()
45
+ continue
46
+
47
+ return restored_client
48
+ raise NoDeviceConnectedError()
49
+
50
+ def __init__(self, udid: str, version: str, service: ServiceConnection) -> None:
17
51
  self.udid = udid
18
- self.version: Optional[str] = None
19
- self.query_type: Optional[str] = None
20
- self.label: Optional[str] = None
21
- self.service: Optional[ServiceConnection] = None
22
-
23
- async def connect(self, client_name: str = DEFAULT_CLIENT_NAME) -> None:
24
- self.service = ServiceConnection.create_using_usbmux(self.udid, self.SERVICE_PORT,
25
- connection_type='USB')
26
- await self.service.aio_start()
27
- self.label = client_name
28
- self.query_type = await self.service.aio_send_recv_plist({'Request': 'QueryType'})
29
- self.version = self.query_type.get('RestoreProtocolVersion')
52
+ self.version = version
53
+ self.service = service
54
+ self.label = DEFAULT_LABEL
30
55
 
31
- assert self.query_type.get('Type') == 'com.apple.mobile.restored', f'wrong query type: {self.query_type}'
56
+ async def _connect(self) -> None:
57
+ self.hardware_info = (await self.query_value("HardwareInfo"))["HardwareInfo"]
58
+ self.ecid = self.hardware_info["UniqueChipID"]
59
+ self.saved_debug_info = (await self.query_value("SavedDebugInfo"))["SavedDebugInfo"]
32
60
 
33
61
  @staticmethod
34
62
  def _get_or_verify_udid(udid: Optional[str] = None) -> str:
@@ -41,36 +69,28 @@ class RestoredClient:
41
69
  return device.serial
42
70
 
43
71
  async def query_value(self, key: Optional[str] = None) -> Any:
44
- req = {'Request': 'QueryValue', 'Label': self.label}
72
+ req = {"Request": "QueryValue", "Label": self.label}
45
73
 
46
74
  if key:
47
- req['QueryKey'] = key
75
+ req["QueryKey"] = key
48
76
 
49
77
  return await self.service.aio_send_recv_plist(req)
50
78
 
51
79
  async def start_restore(self, opts: Optional[RestoreOptions] = None) -> None:
52
- req = {'Request': 'StartRestore', 'Label': self.label, 'RestoreProtocolVersion': self.version}
80
+ req = {"Request": "StartRestore", "Label": self.label, "RestoreProtocolVersion": self.version}
53
81
 
54
82
  if opts is not None:
55
- req['RestoreOptions'] = opts.to_dict()
83
+ req["RestoreOptions"] = opts.to_dict()
56
84
 
57
- self.logger.debug(f'start_restore request: {req}')
85
+ logger.debug(f"start_restore request: {req}")
58
86
 
59
87
  return await self.service.aio_send_plist(req)
60
88
 
61
89
  async def reboot(self) -> dict:
62
- return await self.service.aio_send_recv_plist({'Request': 'Reboot', 'Label': self.label})
90
+ return await self.service.aio_send_recv_plist({"Request": "Reboot", "Label": self.label})
63
91
 
64
92
  async def send(self, message: dict) -> None:
65
93
  await self.service.aio_send_plist(message)
66
94
 
67
95
  async def recv(self) -> dict:
68
96
  return await self.service.aio_recv_plist()
69
-
70
- @cached_property
71
- async def hardware_info(self) -> dict[str, Any]:
72
- return (await self.query_value('HardwareInfo'))['HardwareInfo']
73
-
74
- @property
75
- async def saved_debug_info(self) -> dict[str, Any]:
76
- return (await self.query_value('SavedDebugInfo'))['SavedDebugInfo']