feat: use devicekit instrumentation for android view tree dump#233
Conversation
…iautomator fallback tries com.mobilenext.devicekit/.ViewTreeDump first via am instrument, falls back to uiautomator dump if devicekit is not installed or fails.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
Cache: Disabled due to data retention organization setting Knowledge base: Disabled due to data retention organization setting WalkthroughThe PR adds DeviceKit JSON support for UI hierarchy extraction (new internal structs, DeviceKit fetch via am instrument, JSON parsing, and recursive conversion to types.ScreenElement), and refactors DumpSourceRaw/DumpSource to prefer DeviceKit output with UIAutomator XML fallback. It also adds a context-aware adb helper, exports GetAppVersion on AndroidDevice, and updates the Android agent APK version and its pinned SHA-256; agent detection now fills missing installed app Version by querying the device. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@devices/android.go`:
- Around line 1336-1347: The current getDeviceKitDump function re-parses the
instrumentation payload into deviceKitNode types and re-marshals them (via
deviceKitHierarchy), dropping any unmodeled fields so DumpSourceRaw is no longer
the raw JSON; change getDeviceKitDump to return the original instrumentation
payload bytes/string directly (the raw JSON produced by the device) instead of
calling json.Marshal(deviceKitHierarchy{Hierarchy: nodes}). Locate the code that
fetches/parses the instrumentation output (used by getDeviceKitNodes or the
underlying fetch function) and either expose the raw payload there or add a new
path in getDeviceKitDump that reads and returns the raw payload unchanged so
DumpSourceRaw remains faithful to the device output.
- Around line 1305-1308: getDeviceKitNodes currently calls runAdbCommand without
any timeout causing DumpSource/DumpSourceRaw to block if adb/instrument hangs;
modify getDeviceKitNodes to create a context with a reasonable deadline (e.g.
context.WithTimeout) and call a timeout-aware adb helper (either an existing
runAdbCommandContext or extend runAdbCommand to accept a context) so the
instrumentation call in getDeviceKitNodes will be cancelled on timeout and
return an error that lets the code fall back to UIAutomator; reference
getDeviceKitNodes and runAdbCommand (or implement runAdbCommandContext) and
ensure the timeout error is propagated up from getDeviceKitNodes to the callers
of DumpSource/DumpSourceRaw.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
| func (d *AndroidDevice) getDeviceKitDump() (string, error) { | ||
| nodes, err := d.getDeviceKitNodes() | ||
| if err != nil { | ||
| return "", err | ||
| } | ||
|
|
||
| jsonBytes, err := json.Marshal(deviceKitHierarchy{Hierarchy: nodes}) | ||
| if err != nil { | ||
| return "", fmt.Errorf("failed to serialize devicekit hierarchy: %w", err) | ||
| } | ||
|
|
||
| return string(jsonBytes), nil |
There was a problem hiding this comment.
Keep DumpSourceRaw actually raw.
This helper parses the instrumentation payload into deviceKitNode and then marshals it back. Any fields DeviceKit emits that are not modeled here are dropped, so --format raw no longer reflects the device's actual JSON payload.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@devices/android.go` around lines 1336 - 1347, The current getDeviceKitDump
function re-parses the instrumentation payload into deviceKitNode types and
re-marshals them (via deviceKitHierarchy), dropping any unmodeled fields so
DumpSourceRaw is no longer the raw JSON; change getDeviceKitDump to return the
original instrumentation payload bytes/string directly (the raw JSON produced by
the device) instead of calling json.Marshal(deviceKitHierarchy{Hierarchy:
nodes}). Locate the code that fetches/parses the instrumentation output (used by
getDeviceKitNodes or the underlying fetch function) and either expose the raw
payload there or add a new path in getDeviceKitDump that reads and returns the
raw payload unchanged so DumpSourceRaw remains faithful to the device output.
Summary
com.mobilenext.devicekit/.ViewTreeDumpviaam instrumentfirst for the Android UI element tree dumpuiautomator dumpif devicekit is not installed or the instrumentation failsINSTRUMENTATION_STATUS: json=...) and maps it toScreenElementthe same way uiautomator XML doesTest plan
DumpSourcereturns elements via the new pathdump --format rawreturns JSON string when devicekit is available, XML string otherwise