androidctl 0.1.0__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 (187) hide show
  1. androidctl/__init__.py +5 -0
  2. androidctl/__main__.py +4 -0
  3. androidctl/_version.py +1 -0
  4. androidctl/app.py +73 -0
  5. androidctl/cli_options.py +27 -0
  6. androidctl/command_payloads.py +264 -0
  7. androidctl/command_views.py +157 -0
  8. androidctl/commands/__init__.py +1 -0
  9. androidctl/commands/actions.py +236 -0
  10. androidctl/commands/adb_wireless.py +157 -0
  11. androidctl/commands/close.py +30 -0
  12. androidctl/commands/connect.py +69 -0
  13. androidctl/commands/execute.py +179 -0
  14. androidctl/commands/list_apps.py +26 -0
  15. androidctl/commands/observe.py +26 -0
  16. androidctl/commands/open.py +41 -0
  17. androidctl/commands/plumbing.py +58 -0
  18. androidctl/commands/run_pipeline.py +307 -0
  19. androidctl/commands/screenshot.py +29 -0
  20. androidctl/commands/setup.py +301 -0
  21. androidctl/commands/wait.py +60 -0
  22. androidctl/daemon/__init__.py +1 -0
  23. androidctl/daemon/client.py +348 -0
  24. androidctl/daemon/discovery.py +190 -0
  25. androidctl/daemon/launcher.py +26 -0
  26. androidctl/daemon/owner.py +349 -0
  27. androidctl/errors/__init__.py +1 -0
  28. androidctl/errors/mapping.py +149 -0
  29. androidctl/errors/models.py +16 -0
  30. androidctl/exit_codes.py +8 -0
  31. androidctl/output.py +147 -0
  32. androidctl/parsing/__init__.py +1 -0
  33. androidctl/parsing/duration.py +17 -0
  34. androidctl/parsing/open_target.py +51 -0
  35. androidctl/parsing/refs.py +12 -0
  36. androidctl/parsing/screen_id.py +10 -0
  37. androidctl/parsing/wait.py +70 -0
  38. androidctl/renderers/__init__.py +110 -0
  39. androidctl/renderers/_paths.py +109 -0
  40. androidctl/renderers/xml.py +234 -0
  41. androidctl/renderers/xml_projection.py +732 -0
  42. androidctl/resources/__init__.py +1 -0
  43. androidctl/resources/androidctl-agent-0.1.0-release.apk +0 -0
  44. androidctl/setup/__init__.py +1 -0
  45. androidctl/setup/accessibility.py +159 -0
  46. androidctl/setup/adb.py +586 -0
  47. androidctl/setup/apk_resource.py +29 -0
  48. androidctl/setup/pairing.py +70 -0
  49. androidctl/setup/verify.py +175 -0
  50. androidctl/workspace/__init__.py +3 -0
  51. androidctl/workspace/resolve.py +27 -0
  52. androidctl-0.1.0.dist-info/METADATA +217 -0
  53. androidctl-0.1.0.dist-info/RECORD +187 -0
  54. androidctl-0.1.0.dist-info/WHEEL +5 -0
  55. androidctl-0.1.0.dist-info/entry_points.txt +3 -0
  56. androidctl-0.1.0.dist-info/licenses/LICENSE +674 -0
  57. androidctl-0.1.0.dist-info/top_level.txt +3 -0
  58. androidctl_contracts/__init__.py +55 -0
  59. androidctl_contracts/_version.py +1 -0
  60. androidctl_contracts/_wire_helpers.py +31 -0
  61. androidctl_contracts/base.py +142 -0
  62. androidctl_contracts/command_catalog.py +414 -0
  63. androidctl_contracts/command_results.py +630 -0
  64. androidctl_contracts/daemon_api.py +335 -0
  65. androidctl_contracts/errors.py +44 -0
  66. androidctl_contracts/paths.py +5 -0
  67. androidctl_contracts/public_screen.py +579 -0
  68. androidctl_contracts/user_state.py +23 -0
  69. androidctl_contracts/vocabulary.py +82 -0
  70. androidctld/__init__.py +5 -0
  71. androidctld/__main__.py +63 -0
  72. androidctld/_version.py +1 -0
  73. androidctld/actions/__init__.py +1 -0
  74. androidctld/actions/action_target.py +142 -0
  75. androidctld/actions/capabilities.py +539 -0
  76. androidctld/actions/executor.py +894 -0
  77. androidctld/actions/focus_confirmation.py +177 -0
  78. androidctld/actions/focused_input_admissibility.py +120 -0
  79. androidctld/actions/fresh_current.py +176 -0
  80. androidctld/actions/postconditions.py +473 -0
  81. androidctld/actions/repair.py +101 -0
  82. androidctld/actions/request_builder.py +204 -0
  83. androidctld/actions/settle.py +146 -0
  84. androidctld/actions/submit_confirmation.py +211 -0
  85. androidctld/actions/submit_routing.py +311 -0
  86. androidctld/actions/type_confirmation.py +257 -0
  87. androidctld/app_targets.py +71 -0
  88. androidctld/artifacts/__init__.py +1 -0
  89. androidctld/artifacts/models.py +26 -0
  90. androidctld/artifacts/screen_lookup.py +241 -0
  91. androidctld/artifacts/screen_payloads.py +109 -0
  92. androidctld/artifacts/writer.py +286 -0
  93. androidctld/auth/__init__.py +1 -0
  94. androidctld/auth/active_registry.py +266 -0
  95. androidctld/auth/secret_files.py +52 -0
  96. androidctld/auth/token_store.py +59 -0
  97. androidctld/commands/__init__.py +1 -0
  98. androidctld/commands/assembly.py +231 -0
  99. androidctld/commands/command_models.py +254 -0
  100. androidctld/commands/dispatch.py +99 -0
  101. androidctld/commands/executor.py +31 -0
  102. androidctld/commands/from_boundary.py +175 -0
  103. androidctld/commands/handlers/__init__.py +15 -0
  104. androidctld/commands/handlers/action.py +439 -0
  105. androidctld/commands/handlers/connect.py +94 -0
  106. androidctld/commands/handlers/list_apps.py +215 -0
  107. androidctld/commands/handlers/observe.py +121 -0
  108. androidctld/commands/handlers/screenshot.py +105 -0
  109. androidctld/commands/handlers/wait.py +286 -0
  110. androidctld/commands/models.py +65 -0
  111. androidctld/commands/open_targets.py +56 -0
  112. androidctld/commands/orchestration.py +353 -0
  113. androidctld/commands/registry.py +116 -0
  114. androidctld/commands/result_builders.py +40 -0
  115. androidctld/commands/result_models.py +555 -0
  116. androidctld/commands/results.py +108 -0
  117. androidctld/commands/semantic_command_names.py +17 -0
  118. androidctld/commands/semantic_error_mapping.py +93 -0
  119. androidctld/commands/semantic_truth.py +135 -0
  120. androidctld/commands/service.py +67 -0
  121. androidctld/config.py +75 -0
  122. androidctld/daemon/__init__.py +1 -0
  123. androidctld/daemon/active_slot.py +326 -0
  124. androidctld/daemon/envelope.py +30 -0
  125. androidctld/daemon/http_host.py +123 -0
  126. androidctld/daemon/ingress.py +112 -0
  127. androidctld/daemon/ownership_probe.py +204 -0
  128. androidctld/daemon/server.py +286 -0
  129. androidctld/daemon/service.py +99 -0
  130. androidctld/device/__init__.py +1 -0
  131. androidctld/device/action_models.py +154 -0
  132. androidctld/device/action_serialization.py +121 -0
  133. androidctld/device/adapters.py +220 -0
  134. androidctld/device/bootstrap.py +153 -0
  135. androidctld/device/connectors.py +231 -0
  136. androidctld/device/errors.py +100 -0
  137. androidctld/device/interfaces.py +58 -0
  138. androidctld/device/parsing.py +320 -0
  139. androidctld/device/rpc.py +483 -0
  140. androidctld/device/schema.py +114 -0
  141. androidctld/device/types.py +161 -0
  142. androidctld/errors/__init__.py +94 -0
  143. androidctld/logging/__init__.py +22 -0
  144. androidctld/observation.py +98 -0
  145. androidctld/protocol.py +53 -0
  146. androidctld/refs/__init__.py +1 -0
  147. androidctld/refs/models.py +54 -0
  148. androidctld/refs/repair.py +284 -0
  149. androidctld/refs/service.py +422 -0
  150. androidctld/rendering/__init__.py +1 -0
  151. androidctld/rendering/screen_xml.py +256 -0
  152. androidctld/runtime/__init__.py +21 -0
  153. androidctld/runtime/kernel.py +548 -0
  154. androidctld/runtime/lifecycle.py +19 -0
  155. androidctld/runtime/models.py +48 -0
  156. androidctld/runtime/screen_state.py +117 -0
  157. androidctld/runtime/state_repo.py +70 -0
  158. androidctld/runtime/store.py +76 -0
  159. androidctld/runtime_policy.py +127 -0
  160. androidctld/schema/__init__.py +5 -0
  161. androidctld/schema/base.py +132 -0
  162. androidctld/schema/core.py +35 -0
  163. androidctld/schema/daemon_api.py +108 -0
  164. androidctld/schema/persistence.py +161 -0
  165. androidctld/schema/persistence_io.py +41 -0
  166. androidctld/schema/validation_errors.py +309 -0
  167. androidctld/semantics/__init__.py +1 -0
  168. androidctld/semantics/compiler.py +610 -0
  169. androidctld/semantics/continuity.py +107 -0
  170. androidctld/semantics/labels.py +252 -0
  171. androidctld/semantics/models.py +25 -0
  172. androidctld/semantics/policy.py +23 -0
  173. androidctld/semantics/public_models.py +123 -0
  174. androidctld/semantics/registries.py +13 -0
  175. androidctld/semantics/submit_refs.py +417 -0
  176. androidctld/semantics/surface.py +254 -0
  177. androidctld/semantics/targets.py +167 -0
  178. androidctld/snapshots/__init__.py +1 -0
  179. androidctld/snapshots/models.py +219 -0
  180. androidctld/snapshots/refresh.py +273 -0
  181. androidctld/snapshots/schema.py +74 -0
  182. androidctld/snapshots/service.py +138 -0
  183. androidctld/text_equivalence.py +67 -0
  184. androidctld/waits/__init__.py +1 -0
  185. androidctld/waits/evaluators.py +216 -0
  186. androidctld/waits/loop.py +305 -0
  187. androidctld/waits/matcher.py +41 -0
@@ -0,0 +1,175 @@
1
+ from __future__ import annotations
2
+
3
+ import time
4
+ from dataclasses import dataclass
5
+ from pathlib import Path
6
+
7
+ from androidctl.commands import run_pipeline
8
+ from androidctl.errors.mapping import map_exception
9
+ from androidctl.setup import adb as setup_adb
10
+ from androidctl_contracts.daemon_api import ConnectCommandPayload, ConnectionPayload
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class SetupVerificationResult:
15
+ command: str
16
+ envelope: str
17
+
18
+
19
+ class SetupVerificationError(RuntimeError):
20
+ def __init__(self, code: str, layer: str, message: str) -> None:
21
+ super().__init__(message)
22
+ self.code = code
23
+ self.layer = layer
24
+ self.message = message
25
+
26
+
27
+ DEFAULT_VERIFY_ATTEMPTS = 5
28
+ DEFAULT_VERIFY_RETRY_DELAY_SECONDS = 0.5
29
+ _RETRYABLE_VERIFY_CODES = {
30
+ "ACCESSIBILITY_DISABLED",
31
+ "ACCESSIBILITY_NOT_READY",
32
+ "DEVICE_AGENT_UNAVAILABLE",
33
+ "DEVICE_DISCONNECTED",
34
+ "DEVICE_NOT_CONNECTED",
35
+ "DEVICE_RPC_TRANSPORT_RESET",
36
+ }
37
+
38
+
39
+ def verify_setup_readiness(
40
+ *,
41
+ serial: str,
42
+ token: str,
43
+ workspace_root: Path | None,
44
+ attempts: int = DEFAULT_VERIFY_ATTEMPTS,
45
+ retry_delay_seconds: float = DEFAULT_VERIFY_RETRY_DELAY_SECONDS,
46
+ ) -> SetupVerificationResult:
47
+ normalized_attempts = max(1, attempts)
48
+ last_error: SetupVerificationError | None = None
49
+ for attempt_index in range(normalized_attempts):
50
+ try:
51
+ return _verify_setup_readiness_once(
52
+ serial=serial,
53
+ token=token,
54
+ workspace_root=workspace_root,
55
+ )
56
+ except SetupVerificationError as error:
57
+ last_error = error
58
+ if (
59
+ attempt_index == normalized_attempts - 1
60
+ or not _is_retryable_verify_error(error)
61
+ ):
62
+ raise
63
+ time.sleep(max(0.0, retry_delay_seconds))
64
+ if last_error is not None:
65
+ raise last_error
66
+ raise SetupVerificationError(
67
+ code="SETUP_VERIFY_FAILED",
68
+ layer="daemon",
69
+ message="daemon connect/readiness verification failed",
70
+ )
71
+
72
+
73
+ def _verify_setup_readiness_once(
74
+ *,
75
+ serial: str,
76
+ token: str,
77
+ workspace_root: Path | None,
78
+ ) -> SetupVerificationResult:
79
+ request = run_pipeline.CliCommandRequest(
80
+ public_command="connect",
81
+ command=ConnectCommandPayload(
82
+ kind="connect",
83
+ connection=ConnectionPayload(
84
+ mode="adb",
85
+ token=token,
86
+ serial=serial,
87
+ ),
88
+ ),
89
+ workspace_root=workspace_root,
90
+ )
91
+ verification_error: SetupVerificationError | None = None
92
+ try:
93
+ outcome = run_pipeline.run_command(request, run_pipeline.build_context())
94
+ except Exception as error:
95
+ verification_error = _verification_error_from_exception(error, token=token)
96
+ if verification_error is not None:
97
+ raise verification_error
98
+
99
+ payload = outcome.payload
100
+ if payload.get("ok") is not True:
101
+ raise _verification_error_from_payload(payload, token=token)
102
+ command = _payload_string(payload, "command")
103
+ envelope = _payload_string(payload, "envelope")
104
+ if command != "connect" or envelope != "bootstrap":
105
+ raise SetupVerificationError(
106
+ code="SETUP_VERIFY_FAILED",
107
+ layer="daemon",
108
+ message="daemon connect returned an unexpected readiness result",
109
+ )
110
+ return SetupVerificationResult(
111
+ command=command,
112
+ envelope=envelope,
113
+ )
114
+
115
+
116
+ def _is_retryable_verify_error(error: SetupVerificationError) -> bool:
117
+ return error.code in _RETRYABLE_VERIFY_CODES
118
+
119
+
120
+ def _verification_error_from_payload(
121
+ payload: dict[str, object],
122
+ *,
123
+ token: str,
124
+ ) -> SetupVerificationError:
125
+ code = _payload_string(payload, "code") or "SETUP_VERIFY_FAILED"
126
+ message = _payload_string(payload, "message") or (
127
+ "daemon connect/readiness verification failed"
128
+ )
129
+ return SetupVerificationError(
130
+ code=code,
131
+ layer=verification_layer_for_code(code),
132
+ message=_redact_sensitive_text(message, token=token),
133
+ )
134
+
135
+
136
+ def _verification_error_from_exception(
137
+ error: Exception,
138
+ *,
139
+ token: str,
140
+ ) -> SetupVerificationError:
141
+ mapped_error = error
142
+ if isinstance(error, run_pipeline.PreDispatchCommandError):
143
+ mapped_error = error.cause
144
+ public_error = map_exception(mapped_error)
145
+ return SetupVerificationError(
146
+ code=public_error.code,
147
+ layer=verification_layer_for_code(public_error.code),
148
+ message=_redact_sensitive_text(public_error.message, token=token),
149
+ )
150
+
151
+
152
+ def verification_layer_for_code(code: str) -> str:
153
+ if code in {"DEVICE_AGENT_UNAUTHORIZED"}:
154
+ return "auth"
155
+ if code in {"ACCESSIBILITY_NOT_READY", "ACCESSIBILITY_DISABLED"}:
156
+ return "accessibility"
157
+ if code in {
158
+ "DEVICE_AGENT_UNAVAILABLE",
159
+ "DEVICE_DISCONNECTED",
160
+ "DEVICE_NOT_CONNECTED",
161
+ }:
162
+ return "server"
163
+ return "daemon"
164
+
165
+
166
+ def _payload_string(payload: dict[str, object], key: str) -> str | None:
167
+ value = payload.get(key)
168
+ if not isinstance(value, str):
169
+ return None
170
+ normalized = value.strip()
171
+ return normalized or None
172
+
173
+
174
+ def _redact_sensitive_text(text: str, *, token: str) -> str:
175
+ return setup_adb.redact_adb_output(text, sensitive_values=(token,))
@@ -0,0 +1,3 @@
1
+ from androidctl.workspace.resolve import resolve_workspace_root
2
+
3
+ __all__ = ["resolve_workspace_root"]
@@ -0,0 +1,27 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from pathlib import Path, PureWindowsPath
5
+
6
+
7
+ def _resolve_user_path(value: Path | str, *, cwd: Path, field_name: str) -> Path:
8
+ raw_value = str(value)
9
+ if os.name != "nt" and PureWindowsPath(raw_value).is_absolute():
10
+ raise ValueError(f"{field_name} must use a host path")
11
+ candidate = Path(raw_value)
12
+ if not candidate.is_absolute():
13
+ candidate = cwd / candidate
14
+ return candidate.resolve()
15
+
16
+
17
+ def resolve_workspace_root(
18
+ *,
19
+ flag_value: Path | None,
20
+ env_value: str | None,
21
+ cwd: Path,
22
+ ) -> Path:
23
+ if flag_value is not None:
24
+ return _resolve_user_path(flag_value, cwd=cwd, field_name="workspace root")
25
+ if env_value:
26
+ return _resolve_user_path(env_value, cwd=cwd, field_name="workspace root")
27
+ return cwd.resolve()
@@ -0,0 +1,217 @@
1
+ Metadata-Version: 2.4
2
+ Name: androidctl
3
+ Version: 0.1.0
4
+ Summary: A Playwright-like CLI for Android automation, built for AI agents.
5
+ Author: Azure99
6
+ License-Expression: GPL-3.0-or-later
7
+ Project-URL: Homepage, https://github.com/Azure99/androidctl
8
+ Project-URL: Repository, https://github.com/Azure99/androidctl
9
+ Project-URL: Issues, https://github.com/Azure99/androidctl/issues
10
+ Keywords: agent,android,adb,automation,cli,accessibility
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Topic :: Software Development :: Testing
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: click<9,>=8.1
22
+ Requires-Dist: httpx<0.29,>=0.27
23
+ Requires-Dist: pydantic<3,>=2.11
24
+ Requires-Dist: pydantic-core<3,>=2.33
25
+ Requires-Dist: typing-extensions<5,>=4.12
26
+ Requires-Dist: typer<1,>=0.16
27
+ Provides-Extra: dev
28
+ Requires-Dist: black; extra == "dev"
29
+ Requires-Dist: build; extra == "dev"
30
+ Requires-Dist: mypy<1.11; extra == "dev"
31
+ Requires-Dist: pytest<9,>=8; extra == "dev"
32
+ Requires-Dist: ruff; extra == "dev"
33
+ Requires-Dist: tomli; extra == "dev"
34
+ Requires-Dist: twine; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ # AndroidCtl
38
+
39
+ AndroidCtl is a local Android automation toolkit for developer and agent
40
+ workflows. It provides a host CLI, a host daemon, shared Python contracts, and an
41
+ Android device agent that can observe the current UI, expose stable element refs,
42
+ run actions, wait for screen changes, and collect artifacts such as screenshots.
43
+
44
+ The usual loop is:
45
+
46
+ ```sh
47
+ androidctl observe
48
+ androidctl tap n3
49
+ androidctl wait --until idle
50
+ androidctl observe
51
+ ```
52
+
53
+ ## Repository Layout
54
+
55
+ - `contracts/`: shared Python wire models and command catalog.
56
+ - `androidctl/`: public CLI, command parsing, daemon discovery, and XML output.
57
+ - `androidctld/`: host daemon, runtime state, command execution, and device RPC.
58
+ - `android/`: Kotlin Android device agent with a foreground RPC service and
59
+ Accessibility service.
60
+
61
+ ## Requirements
62
+
63
+ - Python 3.10.
64
+ - Android SDK platform tools, especially `adb`.
65
+ - An Android 11+ device or emulator with USB debugging enabled.
66
+
67
+ ## Install From PyPI
68
+
69
+ Install the released host tools with the single public distribution:
70
+
71
+ ```sh
72
+ pip install androidctl
73
+ androidctl --help
74
+ ```
75
+
76
+ The `androidctl` distribution includes the CLI, host daemon, and shared Python
77
+ contracts. Do not install separate `androidctld` or `androidctl-contracts`
78
+ distributions.
79
+
80
+ ## Install From Source
81
+
82
+ Create a local Python environment and install AndroidCtl in editable mode:
83
+
84
+ ```sh
85
+ conda create -p ./.conda python=3.10
86
+ ./.conda/bin/python -m pip install -U pip
87
+ ./.conda/bin/python -m pip install -e ".[dev]"
88
+ export PATH="$PWD/.conda/bin:$PATH"
89
+ ```
90
+
91
+ Check the CLI:
92
+
93
+ ```sh
94
+ androidctl --version
95
+ androidctl --help
96
+ ```
97
+
98
+ ## Build The Android Agent
99
+
100
+ Released Python packages include the Android agent APK used by setup. When
101
+ working from source and testing a locally built debug agent, build a debug APK
102
+ and pass it to setup with `--apk`:
103
+
104
+ ```sh
105
+ (cd android && ./gradlew :app:assembleDebug)
106
+ androidctl setup --adb --apk android/app/build/outputs/apk/debug/app-debug.apk
107
+ ```
108
+
109
+ The debug APK is created at:
110
+
111
+ ```sh
112
+ android/app/build/outputs/apk/debug/app-debug.apk
113
+ ```
114
+
115
+ ## Prepare A Device
116
+
117
+ Connect a device with USB debugging enabled and confirm that ADB can see it:
118
+
119
+ ```sh
120
+ adb devices
121
+ ```
122
+
123
+ Run the onboarding helper:
124
+
125
+ ```sh
126
+ androidctl setup --adb
127
+ ```
128
+
129
+ If more than one device is connected, pass the ADB serial:
130
+
131
+ ```sh
132
+ androidctl setup --adb --serial <adb-serial>
133
+ ```
134
+
135
+ Setup installs the Android agent, starts its foreground RPC server, provisions a
136
+ device token, attempts to enable the AndroidCtl Accessibility service, and checks
137
+ that the daemon can talk to the device. If Android blocks automatic
138
+ Accessibility enablement, follow the manual instructions printed by the command
139
+ and rerun setup.
140
+
141
+ ## Optional Wireless ADB
142
+
143
+ Pair and connect from the CLI if you prefer Android wireless debugging:
144
+
145
+ ```sh
146
+ androidctl adb-pair --pair <host:pair-port> --code <pairing-code>
147
+ androidctl adb-connect <host:connect-port>
148
+ androidctl setup --adb --serial <host:connect-port>
149
+ ```
150
+
151
+ ## Basic Usage
152
+
153
+ Observe the current screen:
154
+
155
+ ```sh
156
+ androidctl observe
157
+ ```
158
+
159
+ The output is XML intended for scripts and agents. Interactive elements receive
160
+ refs such as `n1`, `n2`, and `n3`; use those refs in later commands.
161
+
162
+ Common commands:
163
+
164
+ ```sh
165
+ androidctl list-apps
166
+ androidctl open app:com.android.settings
167
+ androidctl open https://example.com
168
+ androidctl tap n3
169
+ androidctl long-tap n3
170
+ androidctl focus n4
171
+ androidctl type n4 "hello from androidctl"
172
+ androidctl submit n4
173
+ androidctl scroll n8 down
174
+ androidctl back
175
+ androidctl home
176
+ androidctl recents
177
+ androidctl notifications
178
+ androidctl wait --until screen-change
179
+ androidctl wait --until gone --ref n3
180
+ androidctl wait --until text-present --text "Done"
181
+ androidctl wait --until app --app com.android.settings
182
+ androidctl screenshot
183
+ androidctl close
184
+ ```
185
+
186
+ Commands use the current workspace by default. For a dedicated runtime state
187
+ directory, pass `--workspace-root <path>` or set `ANDROIDCTL_WORKSPACE_ROOT`.
188
+
189
+ ## Development
190
+
191
+ Run the default verification suite from the repository root:
192
+
193
+ ```sh
194
+ task test
195
+ task lint
196
+ task quality
197
+ ```
198
+
199
+ Useful focused commands:
200
+
201
+ ```sh
202
+ task androidctl:test
203
+ task androidctld:test
204
+ task contracts:test
205
+ task android:test
206
+ task format
207
+ task --list
208
+ ```
209
+
210
+ Source development additionally requires Conda, JDK 17 or newer for Android
211
+ Gradle builds, and `task` for repository shortcuts.
212
+
213
+ Process-level CLI checks are available through:
214
+
215
+ ```sh
216
+ task test:extended
217
+ ```
@@ -0,0 +1,187 @@
1
+ androidctl/__init__.py,sha256=4QtZe7AlfISNcrAe0ma3ZSkgeDDZd3y24es8U74otFc,88
2
+ androidctl/__main__.py,sha256=GhA_jQK0HPEAxwgfSYLfQz8t5uDWTBxCY5icQ_MuVrw,59
3
+ androidctl/_version.py,sha256=kUR5RAFc7HCeiqdlX36dZOHkUI5wI6V_43RpEcD8b-0,22
4
+ androidctl/app.py,sha256=YOr4GQUJhqLsNfVdIqSqMH2CR4NXDjw7_5uSWbIuP6o,2402
5
+ androidctl/cli_options.py,sha256=9jYnxicN8Uonty4ex2D05rXIw5zhDF8KoRIYyaprqhE,611
6
+ androidctl/command_payloads.py,sha256=nJGyfD15COMEvp3XDnVJOIJRIBNGh2c_rbs5kEI_wWA,8878
7
+ androidctl/command_views.py,sha256=AbJgSnPGzb8pBgnjyH1OfIHqHWl-JjjN3TVUnc5vJlc,4483
8
+ androidctl/exit_codes.py,sha256=ZCkgxTVAdN9-jH-EeeTK-xNV3gvEujnqpl9eFJ-BFlU,111
9
+ androidctl/output.py,sha256=dNUnYvmE6660edDFp6lvUxT76sn1cP7_AqSZCk3dtzc,4216
10
+ androidctl/commands/__init__.py,sha256=TOMJAh6GCkJ3gAlu1iZo1eKtdBP7_MzCeUrxozBCW2Y,28
11
+ androidctl/commands/actions.py,sha256=Aq5BoBv3r9SkZ6QIwqLIpr9Y-u5MIMlywrplvtHd1SU,7947
12
+ androidctl/commands/adb_wireless.py,sha256=PC3b2GN1BV4u5ekyfbS6DXk2uBdKN7mcgnDHepzBxas,4817
13
+ androidctl/commands/close.py,sha256=B4yu2bbPdjJSi3P7g_p5zXAS8b4wtcbUZw4mlTHILnM,949
14
+ androidctl/commands/connect.py,sha256=-PEjLMu8eH5DaMyqIKO1DGPGOU3eHrPbOwQ9vCVOoKw,2783
15
+ androidctl/commands/execute.py,sha256=Pn3oehixkwf0PKl2kJlhVmUCPjmsWK2tbUtqMHXSpIM,5215
16
+ androidctl/commands/list_apps.py,sha256=EE8_4EbI0Ku6RKbmNhH6_AA1HIEZecs1tMDBIwONfHI,821
17
+ androidctl/commands/observe.py,sha256=4UtSsP_xtf9wAaa4WZ3ZQ5bzAW5lsAYKYGi5zjhNloY,812
18
+ androidctl/commands/open.py,sha256=H0qJoBhc69UUrfcwS-CM9VjQ74sXREO46oU5sFKK92Q,1386
19
+ androidctl/commands/plumbing.py,sha256=GQjqVe1BMjKWD8EFWB7GhyF4LcEXw5tNuszBHURLiFM,1648
20
+ androidctl/commands/run_pipeline.py,sha256=HIu5AkqE7zYAngreWZkBE4ajEEr7h5gV17VOD5VzMpY,8988
21
+ androidctl/commands/screenshot.py,sha256=IOxiKWaTApAVmDAG6yO7k56heYWuiGYgnchN1q9P1m8,931
22
+ androidctl/commands/setup.py,sha256=l0RClZQY5B0sap1BkHC9qghZTLun_H27Fd9_QE9tLRA,9446
23
+ androidctl/commands/wait.py,sha256=gyrOwVYsn3xiqt9bOMlIMHZqcB2RgsKwbuwftvn5oDg,2239
24
+ androidctl/daemon/__init__.py,sha256=yhRVLJ_xwA8TqEEMVLQjE0aaS27S295SvVMs_mhIAlw,47
25
+ androidctl/daemon/client.py,sha256=QyAOsg0SlrylE2As-HH-z3Ha7H1ykbceotrzIiDQBf8,11337
26
+ androidctl/daemon/discovery.py,sha256=of3aERrkWhSGRu2jxPhne_NnbELWCRB6E8ry6ft2R_g,5683
27
+ androidctl/daemon/launcher.py,sha256=8cN0KwP3nR0hlBQHC277CosoBnCPYQ5G03JKWYWHQP8,653
28
+ androidctl/daemon/owner.py,sha256=MuXC2D3VWlkkERdH8dU3N7DHah5wglqmLX53UI6S7Mc,11037
29
+ androidctl/errors/__init__.py,sha256=is9JaQ9Keci_dD7neHD42h2ArBptl2O_wQ7qbM0re3M,51
30
+ androidctl/errors/mapping.py,sha256=RXIcs_G28GoIgOIMDZw_St7xMHqt7qjmAmo_0a3PzAU,5028
31
+ androidctl/errors/models.py,sha256=Sozu8ynlSPO3xj2Em0H429Wby3K2K2QBfQwjfwcLv-c,316
32
+ androidctl/parsing/__init__.py,sha256=sFJFYJswlm2ScWPZDGRhwrG1kENiKXRb0DTtwYAAAMk,40
33
+ androidctl/parsing/duration.py,sha256=X6K5VhDg9NtVvNIAQyYpKr3nhb97FCh3fwM2MJLQmXQ,468
34
+ androidctl/parsing/open_target.py,sha256=QKLOtjp4lJoDnylLzevx5vy3HeOjfUkWy-qlfCKUd2g,1586
35
+ androidctl/parsing/refs.py,sha256=nP6lF4ooBzZC1cV8b3x3gwy26grkvxOmJKcvQP9XxYY,284
36
+ androidctl/parsing/screen_id.py,sha256=wU47dhXhhwjsPpppI0AOhxGBmamKDDTfQsPdZOxYGxU,276
37
+ androidctl/parsing/wait.py,sha256=OXSHPTNACy9lkqoV692stC4jW9ilj3W_pUT_SizrU1g,2461
38
+ androidctl/renderers/__init__.py,sha256=nVYSLnyjbeXAc6WfowqMRFva5nx1NKfrPJ7GbpetTfA,4093
39
+ androidctl/renderers/_paths.py,sha256=oMW4F60_jrtv5eDR-a1EUkGpH6GjKGuC24oH5J75TYQ,3219
40
+ androidctl/renderers/xml.py,sha256=9qXnPj_Mls9j52Z6uI0BW6KxQQISDRho28aoey-nUEw,7137
41
+ androidctl/renderers/xml_projection.py,sha256=UvwqyPwziBcKZqO0M7c6tMEQIADYcMwSPXYn6m7PNgE,21555
42
+ androidctl/resources/__init__.py,sha256=u59_QkN6Zxtq8l_GSEWaXnVXI9YIvH_4X5D0BG_sZfc,51
43
+ androidctl/resources/androidctl-agent-0.1.0-release.apk,sha256=gtILGdzX3pd4A23mj4CwqfKVsrG0Ir1eX6iIteR1B9U,1817062
44
+ androidctl/setup/__init__.py,sha256=gWBddRbWC4cxkLNSW38ccbqnfMkYUQCL3XbM8mnpdoo,31
45
+ androidctl/setup/accessibility.py,sha256=F6c1THAnTXUPsYZgab0j4NAAZtGscVINb3LbC1-jDVw,5096
46
+ androidctl/setup/adb.py,sha256=sd0tA8AOvBe6jiYXZ1hfNBVA5_zQg6xKdHflB3OxfYc,16808
47
+ androidctl/setup/apk_resource.py,sha256=avl5f6SxwI6Qmwf4t0tEdwxZowNz7GlshCHXUgKDdSM,992
48
+ androidctl/setup/pairing.py,sha256=-6gVN7tmGjONYmzRuWVQ88v-qmR3QCWvosiEi8Yx-Nw,2091
49
+ androidctl/setup/verify.py,sha256=8ZbQzLleRowW1B4PT6wuYUm-1XC73L6pmBHU3qdiDig,5296
50
+ androidctl/workspace/__init__.py,sha256=w3-mYU1pRyZh9GO0Urgk015vprsCDBZcWrrQbi5XR3A,102
51
+ androidctl/workspace/resolve.py,sha256=wA6XnkAnYLGarrDuRDVG5UqeQVPZ9qKlPt1da0oD_tE,826
52
+ androidctl-0.1.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
53
+ androidctl_contracts/__init__.py,sha256=M6xk80zkDwzA3GRvo7gp_fzTYaSAhC7VNI84606QOU0,1706
54
+ androidctl_contracts/_version.py,sha256=kUR5RAFc7HCeiqdlX36dZOHkUI5wI6V_43RpEcD8b-0,22
55
+ androidctl_contracts/_wire_helpers.py,sha256=F21mP752Vb2U3ZlkoxbcA4M9JKrHhIvyFfTXIYoTDDU,793
56
+ androidctl_contracts/base.py,sha256=BH0W1UBPqHFQ0zYLBVF_DnCKwgodBdDvKl_JnbDSywo,4455
57
+ androidctl_contracts/command_catalog.py,sha256=Mvd5ehWyuoHThGFhAQcMVD0V0xkhGwLkzSHnIRNUQrQ,13107
58
+ androidctl_contracts/command_results.py,sha256=ziWr74mymmhVJp6ecEPv7sVIWWrmrN8b1eNoMCHLYCY,22623
59
+ androidctl_contracts/daemon_api.py,sha256=DxNg_ub-gM0uDbn3YtxCxFZimvIgw5fd371Wgquzyrg,8846
60
+ androidctl_contracts/errors.py,sha256=5VjpycZ4UqCuEDfWWOn_F7umqe30qu2tYoOrNrffsf8,1600
61
+ androidctl_contracts/paths.py,sha256=vQ45eL41PRzFpX6s_w5S8gKMQpfBaMLIWEgCZk92FpU,133
62
+ androidctl_contracts/public_screen.py,sha256=ejLlBFKDlMOevsOe4H7KOhJr_ByiPWnJApoOakbgzKk,18374
63
+ androidctl_contracts/user_state.py,sha256=ABoI_2RAN-pWEigrBTkrej3lCdqY4AMWNPHU_CBtlrY,459
64
+ androidctl_contracts/vocabulary.py,sha256=eozqR7g2ZLB6feJLzNuSTbf7zxR2oUAdALuoJyoyPRs,1809
65
+ androidctld/__init__.py,sha256=9q6Hoe4SX4bhDh-EahJPl5csFlEBRkTRZ3ZzMm8y95c,119
66
+ androidctld/__main__.py,sha256=kw-DhZgo54nwfB3obhjNIZEGLKLzoNlvFa11OLnT7NA,1734
67
+ androidctld/_version.py,sha256=kUR5RAFc7HCeiqdlX36dZOHkUI5wI6V_43RpEcD8b-0,22
68
+ androidctld/app_targets.py,sha256=3AHMB8u_5tbPJWiyN9Ll--tCQJhjveDcsRi9E4ACkLw,2114
69
+ androidctld/config.py,sha256=MVWXvezLo7jZQAgbeNPw7ZQKPcNd7le_zVja4HuW8_E,2365
70
+ androidctld/observation.py,sha256=PvKyqnG78-WLe-TZnmKIPxyz9bNEUWVDgpleoAs6uH8,2883
71
+ androidctld/protocol.py,sha256=eLfaK3OD45PKWgVN7INHOxromDoACmHdiTzndOWtAws,1209
72
+ androidctld/runtime_policy.py,sha256=v058l3tQuS5485d-Xm4hDL4kYZUxm6xPrnUXCPJunKE,4632
73
+ androidctld/text_equivalence.py,sha256=jTrCWds5vsYiXW1DzKs1qQPBcG3XV-GH63BKN4siMBg,1688
74
+ androidctld/actions/__init__.py,sha256=VRHZcFSmhhqFWVtaEQezKTgVer3bCszConeqEGxdMRs,46
75
+ androidctld/actions/action_target.py,sha256=sajRoLf-TRtVBihR2cXkmqo4IjKHTmVWdi-TjfeDl54,4229
76
+ androidctld/actions/capabilities.py,sha256=ssHPhcpc6IHGPbJRQa_-edZY51_vkKumZ2xoLIq_uVU,16290
77
+ androidctld/actions/executor.py,sha256=sSqRjB5u6ULNdkw8cgFeDt20eE7NcGhnmOPuz1layk4,33084
78
+ androidctld/actions/focus_confirmation.py,sha256=ZxCPUbebTq71rfb29B5B02RC6S2C9NvPj_5B-jbBf3Q,5395
79
+ androidctld/actions/focused_input_admissibility.py,sha256=pr6hD0HxJRltuqPy0Iua3QSV6NPY9-uot3BxlfpMl_Y,2880
80
+ androidctld/actions/fresh_current.py,sha256=gGvQooDdXqvwAmZ38DkeYgLuLZf6DAS3nK-541dmc-Y,5383
81
+ androidctld/actions/postconditions.py,sha256=pTrrKFRo5zA5jKZ0w2uqK7DAvo807nzsMxqk_m4SdKA,15279
82
+ androidctld/actions/repair.py,sha256=LElYO95rwO1GdFlKvlDjYTJu9DrSpc_0atwc6reUKhI,3509
83
+ androidctld/actions/request_builder.py,sha256=cCsdeweecx-Xi5OfczgDPVxO2j_dyBtZPDkorjh1G64,6996
84
+ androidctld/actions/settle.py,sha256=BCdAXHofHRfSpDkBRjbLbUBfcr9Ts4io7tB66-Kggps,5241
85
+ androidctld/actions/submit_confirmation.py,sha256=4SIKWuCrbPQdCPyB5qIqqclkVD0nO_js4_7an1uiGkk,6833
86
+ androidctld/actions/submit_routing.py,sha256=gj2UAbLtS9M2hCo20pOZMfYe-sdOAIjNp0IaB9nYGgQ,9877
87
+ androidctld/actions/type_confirmation.py,sha256=WCHSh5jkQN_GRaSj5fGeYbnDvImH6iwULN_l2JfHkgc,7779
88
+ androidctld/artifacts/__init__.py,sha256=pgyeikmFTdMgQhoHeuW5FMSBI1JVHoJAD89CPJYE8lM,40
89
+ androidctld/artifacts/models.py,sha256=Osx_sZ2h_J6sg1xJ_SzqiopgbVFhf1OmSDU_IMZC5Ic,691
90
+ androidctld/artifacts/screen_lookup.py,sha256=28WcIBA4eejzFlOvSh_xJywf2dmkCcsE2HJNo4Tj47s,7447
91
+ androidctld/artifacts/screen_payloads.py,sha256=8h6BRlt3nWzowsDrLuw9ZacizSEacyeTrnm3enmEoGw,3228
92
+ androidctld/artifacts/writer.py,sha256=0jdMzHddOwJdtqmSqYDJ7vPlJOOtTmHsQlfxmogmbyE,9778
93
+ androidctld/auth/__init__.py,sha256=xwCyyzQ8Iu7DzOqyEgSHfsZpwoZ5jXMCuDNGZJCDCmo,46
94
+ androidctld/auth/active_registry.py,sha256=o05fjCsQuvq6eZlRupq3V0mDJWG1SkUk-GLzyQK-y2g,9060
95
+ androidctld/auth/secret_files.py,sha256=94Vr8J_y_msoPeh85xGuDzHPzO-7UTzEyTS4qyq9h1Y,1512
96
+ androidctld/auth/token_store.py,sha256=fGygjQ5pmH4pYR_-N9jorbKBXQ1-PVsIRhknplXx0E4,1722
97
+ androidctld/commands/__init__.py,sha256=4MevNZf54MkxiYjdda4GQE-xD7gIPegkdad6jphxwZY,40
98
+ androidctld/commands/assembly.py,sha256=56QlUQi3CgvNeA2Qz0lS7LpgGyBNjikOV6XVfCxr0v8,8605
99
+ androidctld/commands/command_models.py,sha256=3iAac3W48Xqn-bD1ukIQDUmQ1U2nJpizJPOykxrHnJw,5983
100
+ androidctld/commands/dispatch.py,sha256=DRLChzI_BR6HvAmaym14Bsu4_ItmNXn1gODpy1fBqAE,4154
101
+ androidctld/commands/executor.py,sha256=WxrnZGMoxBR8o6ZHc3NeaBjrhIe0SMeFOpP79EsWnfY,806
102
+ androidctld/commands/from_boundary.py,sha256=f7ypzu7qLGwd5fjDEPnAucqUdcm8DDrn70JHhxrKDdU,5557
103
+ androidctld/commands/models.py,sha256=zhe92Nj5SMar079mo0Nk0NFdykLF3JEB-Yl7luviI9Y,1854
104
+ androidctld/commands/open_targets.py,sha256=gZ2rABIKSmhIBrEoYnVcl23eNqsBQXg1ssyY1QtLCBM,1326
105
+ androidctld/commands/orchestration.py,sha256=S_rZc4YFwVA-6ToDYnrhJ8fGooMAXrW3M7lvaczz_kc,12074
106
+ androidctld/commands/registry.py,sha256=rbXGItAtDrebQB8gvX7zhlWkBHJ0GUZ9Z8e8pjtTxig,3138
107
+ androidctld/commands/result_builders.py,sha256=TVi8d7mi8GKnCfkXtYIgs4y4Ioj5vo8FJVBg29AosZo,1248
108
+ androidctld/commands/result_models.py,sha256=8bMX2vGgC1N_3laFC6xok2HFLhAxXY6qm4d2opa0tNs,17161
109
+ androidctld/commands/results.py,sha256=AURTnob6IpEAva_NB-00L1TZONXFnay1L1Bn_sYeIkU,3847
110
+ androidctld/commands/semantic_command_names.py,sha256=X-3755hwLJwvMteIXU92uK9HynvVO8IhryUUPEfxAfA,573
111
+ androidctld/commands/semantic_error_mapping.py,sha256=BYSpXaJk_ZA9TB70HXibaOopHY2HXi91L0KkFViksnU,2902
112
+ androidctld/commands/semantic_truth.py,sha256=hQBE-plbPNFBbvR2fRz5RhhW6Ym0x5xUReqkH8XE34E,4270
113
+ androidctld/commands/service.py,sha256=_uWM0kl3ljmkv_Vb-kPIjHlEIrHNNKZYcvpZJYvr-GA,2494
114
+ androidctld/commands/handlers/__init__.py,sha256=zaOUCB4TDV38SgtgSOiynznq6iK7ydGEeBhquPxNTbY,549
115
+ androidctld/commands/handlers/action.py,sha256=kfdBFY7u1TeRgixS3tfEzY_XtsG3jVGtLpw9OgCBjuc,16107
116
+ androidctld/commands/handlers/connect.py,sha256=tOntgPC-cjukSYYgIHsoikiybIhLruUL_h36A3DRDuw,3500
117
+ androidctld/commands/handlers/list_apps.py,sha256=I4eqSKpxe6k0abAWOyYfVt3fjPaRoGQ0iAo90lg8wfU,6923
118
+ androidctld/commands/handlers/observe.py,sha256=nPMyjKr5l2ZjvUbufrF2KsApWav_ic1XD6oY7AM4EPM,4759
119
+ androidctld/commands/handlers/screenshot.py,sha256=ifQnrYo2UPAPUbsf9WOqSWq3M_ZqANVBHUqPikNM9iM,4101
120
+ androidctld/commands/handlers/wait.py,sha256=GdO1x2l3xTus8-kLeRfHC0LySQJKLlHqYJ7qLx6iHRY,9430
121
+ androidctld/daemon/__init__.py,sha256=MdeDacbbOgSdghwWIEXu8b5KFuoDP9CZKPsZwS8BS_0,34
122
+ androidctld/daemon/active_slot.py,sha256=DxylWRPgW2ZQCfQxxJlzFStMfTMRAEf4kpoED92OL6w,11215
123
+ androidctld/daemon/envelope.py,sha256=J-Fx7yMjuo62ECH6lh6JOM_8SJH0XQ53CM0b6z5_J5A,920
124
+ androidctld/daemon/http_host.py,sha256=4DUpAUWOvXaLVq4NY5SOPsdGdfRmI_6pOJzKrKBHia0,4169
125
+ androidctld/daemon/ingress.py,sha256=OEzpov43eWlMofr9rTR57H8j-A71FrJEiH5AQzgD9ns,3315
126
+ androidctld/daemon/ownership_probe.py,sha256=ywbRyyjspywbn6OCh0GID3pHHuHpB8Dy0fOD_G_gmEs,6740
127
+ androidctld/daemon/server.py,sha256=oSDgAMwTdVjAy3rgoe8KIFQkcxDlfRxOZ2hOkcBbmnw,10731
128
+ androidctld/daemon/service.py,sha256=RuVt-s7-XsmhgzWDcjGHGgvbIx2JKqUIR63AweYHb9A,3768
129
+ androidctld/device/__init__.py,sha256=kc10OpxuwURGmUtDTLVKcJZZBmZIYSR2lw5-d6aa2RM,59
130
+ androidctld/device/action_models.py,sha256=97ur2nMt6uWEym3YcRlcKcz-6ZCuZY1GDCvbQJiU3RM,3264
131
+ androidctld/device/action_serialization.py,sha256=HJk591MX4EDULwBLS2mPtqfECKKFDeZvvBmywNOvGNw,4083
132
+ androidctld/device/adapters.py,sha256=Rd4uzAOAkC_3iwW8w52pLPYT_hIynwmsjo1bLEUMkDE,5923
133
+ androidctld/device/bootstrap.py,sha256=SYcEqyASjp_gMFMg864oreWWMP1vyaVBMU7WDGKskKM,5452
134
+ androidctld/device/connectors.py,sha256=r_Cmjx9VBDEAd30jkhs7hzvo1UkGw-FRwkTYDt70lDI,7287
135
+ androidctld/device/errors.py,sha256=4XKJb_xQOVGynfC1PKxDVnqtz7jVQiIW4Mj3QZHsFKs,2486
136
+ androidctld/device/interfaces.py,sha256=Tl6SMhqpMkTN09EjrjlNWC-EBO_L77HdXQUv_MIUKB4,1484
137
+ androidctld/device/parsing.py,sha256=TmP416YuYHnb-t-uKWRLfFZTFxE80lGIlhiLvM2Nf6E,10065
138
+ androidctld/device/rpc.py,sha256=TQrgAUQ0qNDJ8BslixBVPDs_DKgjdwyrbi2eSFN3yPM,15503
139
+ androidctld/device/schema.py,sha256=Z6URyIeRtLnCnH900XyeSuapcO6SjCmUuoVdiCI_1p8,2793
140
+ androidctld/device/types.py,sha256=DcwOceyZFFOlR7QgHXIKMIIlzh7jO8-y2U4YooGzraA,3463
141
+ androidctld/errors/__init__.py,sha256=CxzvddDOq84JLElZFBXTbMFi9yMLs3E5PU1S4Oai9dQ,3202
142
+ androidctld/logging/__init__.py,sha256=n-qpNGF8mGw0zKbTwcylW7HfdglwqIHH7MFPJmkLysc,615
143
+ androidctld/refs/__init__.py,sha256=pRcfAuIhh2a1ta76kerdrq8IUCWa6YGOefMKdQ28Xrc,40
144
+ androidctld/refs/models.py,sha256=iRABst8Uv6fgZhSuQipZTHYUjDhAXDIU3UAyOmHGpFI,1059
145
+ androidctld/refs/repair.py,sha256=QWdh8C8HR2YfwgIze-QXCFHoe_jB-Iwqcuq9gmyYuEw,9087
146
+ androidctld/refs/service.py,sha256=cOucNxw0-M_iHhCfBi-qdLfdu2lKV_QjXhv-4_GTik0,13250
147
+ androidctld/rendering/__init__.py,sha256=bS_SsxNNzFB2MmXVTtCh50KEG-ouC1k261ZG34fY1s0,45
148
+ androidctld/rendering/screen_xml.py,sha256=1rp9e6Qp9khkv0M7SIh_Dx7Kk9vLzcGxis1uYk_9VEo,7656
149
+ androidctld/runtime/__init__.py,sha256=06DLg_p5Cpe5oKsUJ8aP2qDm18A36pfK0wDEGefGSb0,639
150
+ androidctld/runtime/kernel.py,sha256=9M9Qnvp1_RezStz2fW6snvXHnhuJY0bJkCFavQ9q4xg,18528
151
+ androidctld/runtime/lifecycle.py,sha256=z-3BzPfK2t0D8A9WOgwIslt1VSEMUuDoDkBv93j9M7Y,521
152
+ androidctld/runtime/models.py,sha256=lLogOA1bOW8_25Fld4qvS9XbluTBa9x4EM0UmLwQIUM,1872
153
+ androidctld/runtime/screen_state.py,sha256=PvT8L1wqiJc4IqgQC6YsDWWL_H64FEyJse3DU5nZz8U,4290
154
+ androidctld/runtime/state_repo.py,sha256=2VXhuXXCL_JxT57tJUJC3u57eWyusg34Qdxd7S20NhM,2286
155
+ androidctld/runtime/store.py,sha256=6j18HcQ7TerigDRhyuXTo0QMD69cs3RRzX_7rhoCg4A,2697
156
+ androidctld/schema/__init__.py,sha256=dyY1QCYdPK8y3KZIyaw0YrZspalIatGr_HyM5Id6D0k,167
157
+ androidctld/schema/base.py,sha256=Qxe3r9EfVOaYYIG1LM7huZq-gXMGRIxEDVq1mvYk62I,4169
158
+ androidctld/schema/core.py,sha256=BgkCM8SLYfg9UVswFEX2DQFxEE7en0z2sJFgsbM5MhA,1053
159
+ androidctld/schema/daemon_api.py,sha256=n9Y4ZVl81h-dWa0lJd1tXSp0RNkbhr364gr9cgVh5iU,3793
160
+ androidctld/schema/persistence.py,sha256=cEBlpwQDWAxfrbGOScsZcC6yjusnw63WUfTx3dWfqFM,4220
161
+ androidctld/schema/persistence_io.py,sha256=Px5T8QJM0PIa7XjhO3taRecRJGe_3k32-QgNuCsCRPo,1214
162
+ androidctld/schema/validation_errors.py,sha256=1YNQz2Jg7IBLMCNPCi2tgG7O6mASPmezbTzcJ2HxiDU,9696
163
+ androidctld/semantics/__init__.py,sha256=zeg60mmCUfgn-klJ80OrqwlImNJuIhwmidByRrKluHI,35
164
+ androidctld/semantics/compiler.py,sha256=O99MifSaytK5NQoJHcchgjVcNrB30UT1CcLzDiWHc3E,20765
165
+ androidctld/semantics/continuity.py,sha256=nSHqV7sIbMj-lQ6p0cimJokrp0fMfxUfXuk1XE196Wc,2912
166
+ androidctld/semantics/labels.py,sha256=mqiNGP36qgd59xlotbd_bbOCB9q1u1IiY6ivblnX3qo,7536
167
+ androidctld/semantics/models.py,sha256=cSu4JtnKhDp0WPq8Bxge6WKhnXyef68FU4NvB3CdR1w,481
168
+ androidctld/semantics/policy.py,sha256=ccdYeVCE6wtIFd39hG-PfIVAcRthJAipBCBrAPAVamM,476
169
+ androidctld/semantics/public_models.py,sha256=Q47DiIlL31pIhhq_312VNLl8EU6j-UFanMntBkNzth4,3188
170
+ androidctld/semantics/registries.py,sha256=SYSM7xFyVcgDQ-i6WnBUzNMFZFE30sqnGOHzyvkY1a4,220
171
+ androidctld/semantics/submit_refs.py,sha256=1MAQbsJP_jHfRiUfoFNXh2--iJmSxvBiWT6ZuWmVNl0,12160
172
+ androidctld/semantics/surface.py,sha256=RDoqnZsyv-ASbls9-XxI4ZWCYWD2Q58-Ub1ztMHpuds,7538
173
+ androidctld/semantics/targets.py,sha256=-sZXnx7XpO6U5u03FZ8JAh2NeNLKhjre0GGrGbpe_zQ,5083
174
+ androidctld/snapshots/__init__.py,sha256=q635p3g0rYMDjvu_IL0gG2BuLrn5WXXylVf03B0El5o,41
175
+ androidctld/snapshots/models.py,sha256=C8snjtlbRp-3fhAZDuhwelkA9kCsGUMIuJRVjHmMvDE,5945
176
+ androidctld/snapshots/refresh.py,sha256=8kuVAGt679txLBNk8OAFf3HdwcQEB_8wwAgDoJ0qNdk,9217
177
+ androidctld/snapshots/schema.py,sha256=CCuVAx8QUWL9_NGiU0a6rhyH-CkdB7XCaJWRC24CuHo,1760
178
+ androidctld/snapshots/service.py,sha256=tb_r2NnJunlSVxk-DR3MBVDtkti8QNlxQhDGZzuxRXY,4489
179
+ androidctld/waits/__init__.py,sha256=n2hzNv2O0TzW0B1Go-OLCW9fImYvUjJlztrgbAl3CPA,36
180
+ androidctld/waits/evaluators.py,sha256=tWvumuwGAcphErsyHXCNQAeaskRjhDrP-ge-9x-DmQY,6174
181
+ androidctld/waits/loop.py,sha256=pWKw_tFvYjd44FF83Lrx77VUKjZJvdYyRE2Tbxfbcok,9367
182
+ androidctld/waits/matcher.py,sha256=R32R0311B_UA1zhBM1vh7RZp4cNRzIEpGRZWvgP4_d4,1133
183
+ androidctl-0.1.0.dist-info/METADATA,sha256=oFMFXzeAlOUrk4-O8Yclxl5fbhCoAOwgqchHYedHJOQ,5721
184
+ androidctl-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
185
+ androidctl-0.1.0.dist-info/entry_points.txt,sha256=fUx6Rxjn-AyETBewq1ynQQk0sY_UPvGZGtIuBcKd6f0,90
186
+ androidctl-0.1.0.dist-info/top_level.txt,sha256=lDv6wEqTA3pTFY3eTAJ1tbLEKqujJe_i4ugRxe6_gEY,44
187
+ androidctl-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ androidctl = androidctl.app:app
3
+ androidctld = androidctld.__main__:main