Skip to content

test: verify native lifecycle recovery and Android accessibility - #69

Merged
rdlabo merged 1 commit into
mainfrom
test/preview-simulator-lifecycle
Oct 22, 2026
Merged

rdlabo merged 1 commit into
mainfrom
test/preview-simulator-lifecycle

Conversation

@rdlabo

@rdlabo rdlabo commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

The native embedding fixtures did not exercise background/resume and interrupted HTTP recovery or provide a separate native-accessibility comparison. This adds repeatable simulator/emulator checks and startup/memory sampling, with published dependency selection for npm 0.1.3 / SwiftPM v0.1.3 / Maven 0.1.2. SDK production sources are unchanged.

  • iOS verifies actual scene background/resume and HTTP success/interruption/recovery; optimized probe builds retain assertions.
  • Android verifies the same Activity stops/resumes, connection recovery, and a separate Release measurement mode. Functional DOM fallback is explicitly logged and does not count as accessibility acceptance.
  • A Debug-only plain WebView comparator and instrumentation distinguish SDK behavior from provider-dependent empty accessibility trees. Accessibility assertions remain strict even when the DOM renders correctly; the comparator and instrumentation are excluded from the Release APK.

Validation

  • npm run typecheck: passed.
  • npm test: 59 files / 617 tests passed.
  • node --test demo/tests/native-embedding/ios/deadline.test.mjs: 6 tests passed.
  • Repository formatting and git diff --check: passed.
  • Prior native verification on the code included here: iOS Release normal/lifecycle/network, startup-failure and broken-entry scenarios passed. Android Debug full functional acceptance passed without DOM fallback; Release initial display/close measurement passed.
  • Android Debug, instrumentation and Release builds passed; Release manifest excludes the comparator and instrumentation.
  • No physical-device claim; HTTP socket interruption is not airplane-mode testing. Startup and memory samples use different platform measurements and are not comparative benchmarks.

Verification report (2026-10-22)

{
  "npm": "cf-workers-native@0.1.3",
  "swiftRevision": "c02e2a96566d5397c2c1f34242ee2a0c02d0ac36",
  "maven": "io.github.rdlabo:cf-workers-native-android:0.1.2",
  "ios": {
    "device": "iPhone 18 Pro / iOS 27.0 simulator",
    "configuration": "release; probe assertions retained",
    "scenarios": [
      "normal with lifecycle and interrupted connection recovery",
      "startup-failure",
      "broken-entry"
    ],
    "status": "passed",
    "observedContentReadyMs": 1403.7400484085083,
    "simulatorLaunchToSceneMs": 2136,
    "hostRSSKiB": 253744
  },
  "android": {
    "status": "passed",
    "device": "independent Android 36.1 Google Play arm64 emulator",
    "npm": "0.1.3",
    "maven": "0.1.2",
    "acceptanceConfiguration": "debug",
    "checks": [
      "same Activity stop/resume through Home and Recents",
      "native HTTP success/interruption/recovery",
      "navigation and POST",
      "rotation",
      "close/reopen",
      "startup failure",
      "renderer loss",
      "Activity recreation",
      "missing-entry timeout",
      "host cookies, CookieHandler and service-worker isolation"
    ],
    "releaseMeasurement": {
      "configuration": "release",
      "tapAndAccessibilityReadyMs": 4835,
      "hostPSSKiB": 82634,
      "hostRSSKiB": 255104,
      "scope": "initial visible Worker Home and close to host; full functional acceptance is separate Debug run"
    },
    "accessibilityInvestigation": {
      "status": "closed; environment remediation verified",
      "report": "../android-accessibility/investigation.json",
      "verifiedWebView": "155.0.8059.43",
      "plainWebViewPersistentTransitionsPassed": 40,
      "sdkPersistentTransitionsPassed": 40,
      "sdkStatelessObservationsPassed": 20,
      "sdkProductionChangeRequired": false
    }
  },
  "limitations": [
    "Simulator/emulator only; no physical device measurements.",
    "iOS RSS excludes WebKit subprocesses; single sample.",
    "HTTP connection interruption on loopback, not device airplane mode or full offline behavior.",
    "Android elapsed time includes native tap dispatch and UIAutomator polling; it is not directly comparable to iOS content-ready timing.",
    "Android PSS/RSS covers the host process, not all WebView subprocesses.",
    "Single Release samples only; no performance threshold or physical-device claim."
  ],
  "observations": [
    "Earlier existing emulator attempts had APK-install/startup delays. Final acceptance used an independent temporary AVD.",
    "An earlier navigation had empty UIAutomator WebView descendants despite correct DOM and screenshot. Final full functional run passed without DOM fallback. Follow-up investigation reproduced the failure without the SDK on WebView 134.0.6998.135; updating the same emulator to 155.0.8059.43 resolved it in measured runs. Closed as a verification-environment issue, not an outstanding SDK defect. Android remains in this report; broad accessibility certification is not claimed."
  ],
  "validation": {
    "deadlineUnitTests": 6,
    "format": "passed",
    "gitDiffCheck": "passed"
  }
}

Android accessibility investigation

Disposition: closed as a resolved verification-environment issue. The empty
native accessibility tree reproduced in a plain WebView without the SDK on
WebView 134.0.6998.135. Updating the same emulator to WebView 155.0.8059.43
resolved the issue in the measured runs. Keep Android in the verification report;
remove this finding from outstanding SDK defects. No SDK production change is
required for this finding. Preserve the failed-run evidence as the basis for this
classification.

Using npm 0.1.3, Maven SDK 0.1.2 and one Android 36.1 Google Play arm64 emulator:

WebView Host Persistent accessibility result
134.0.6998.135 Plain WebView, default profile Empty web descendants after 9 completed rounds; DOM and screenshot still show Posted verified
134.0.6998.135 Workers SDK Empty web descendants after 2 completed rounds; DOM still shows Posted verified
155.0.8059.43 Plain WebView, default profile 20 rounds / 40 transitions passed
155.0.8059.43 Workers SDK 20 rounds / 40 transitions passed

The plain WebView also lost its heading in 1 of 10 stateless observations on 134;
a subsequent dump recovered it. On 155, all 20 SDK stateless observations passed
without a retry. Keeping UiAutomation connected or explicitly
clearing its cache did not eliminate the 134 failure. Native taps were used for
this comparison: an earlier ACTION_CLICK experiment failed to navigate even the
plain WebView and was excluded from the missing-tree comparison.

The WebView provider was updated on the same emulator for the 134-to-155 comparison;
the host APK, HTML, SDK binaries and accessibility assertions stayed the same. These results implicate the old WebView /
Android accessibility interaction rather than SDK-specific rendering. They do not
identify a particular Chromium fix, establish the first fixed version, or certify
TalkBack. No SDK workaround or new minimum supported WebView version follows from
this limited sample. Record the provider version with every run (webview.txt),
and use the verified 155.0.8059.43 provider when reproducing this environment's
acceptance. The unknown upstream fix and first fixed version are scope limits,
not outstanding SDK remediation tasks. If the same failure recurs with this
verified provider, reopen the investigation with both plain-WebView and SDK
results.

For implementation context, AOSP's dump command
connects, waits for idle, reads a tree and disconnects for each invocation.
Chromium's Android accessibility documentation
describes lazy tree initialization and accessibility caches. These explain why
independent DOM and native-tree evidence is necessary; they do not prove the exact
cause of the observed 134 failure.

Raw XML, screenshots, DOM captures and logs are retained locally under artifacts/android-accessibility/ and artifacts/preview-simulator-0.1.3/; they are not attached to this PR. The results and disposition above are preserved here according to CONTRIBUTING.md, while fixture READMEs retain reproduction instructions.

id: 1,
method: "Runtime.evaluate",
params: {
expression: `(() => { const element = [...document.querySelectorAll('h1,a,button')].find(el => el.textContent.trim() === ${JSON.stringify(text)}); if (!element) return null; const r = element.getBoundingClientRect(); const s = getComputedStyle(element); if (!r.width || !r.height || r.bottom <= 0 || r.top >= innerHeight || s.visibility !== 'visible' || s.display === 'none') return null; return { x: r.x+r.width/2, y: r.y+r.height/2, width: innerWidth, height: innerHeight, url: location.href }; })()`,
@rdlabo
rdlabo merged commit 96eb1cc into main Oct 22, 2026
27 of 28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants