Skip to content

EXP-069 — Generic text input + click dispatch: phone number injected + Next button clicked #6

Description

@Sh-TB

EXP-069 — GENERIC INTERACTION RUNTIME + TELEGRAM LOGIN FLOW CAMPAIGN

Problem:
EXP-068 proved the Login UI with a visible Next button, but there was no way to interact with the UI — no text input dispatch, no click dispatch. The runtime could render a static screenshot but couldn't simulate user interaction.

Evidence:

Metric EXP-068 EXP-069
Text input dispatch not implemented DISPATCHED (view=2827, text='+15551234567')
Click dispatch on Next button not implemented DISPATCHED (view=3869, listener=3897)
onNextPressed called NO YES (10 times)
ConnectionsManager.sendRequest called NO YES (auth.sendCode boundary reached)
Phone field text in view_tree empty '+15551234567'
Text-bearing ViewNodes 49 50 (+1 from phone input)
login_ui.png SHA256 39ca3cd7... 064b82f2...
3-run reproducibility identical identical
Generic regression PASS PASS

Root cause:
No generic interaction subsystem existed. The runtime could execute DEX bytecode and capture View state, but had no API to inject user events (text input, clicks) into the View hierarchy.

Fix:

Phase 2 — Generic text input API

  • Added dispatch_text_input(view_id, text) to DalvikExecutionEngine.
  • Dispatches to ViewShadow.setText via the shadow registry — the SAME path that DEX setText uses.
  • Stores text on the ViewNode, making subsequent getText() calls in DEX bytecode return the new value.
  • Added dispatch_text_input_by_class(class_substring, text) convenience wrapper.
  • GENERIC — no Telegram-specific code. Works for any EditText/TextView.

Phase 6 — Click dispatch integration

  • dispatch_click(view_id) already existed from EXP-060 (used to create LoginActivity by clicking the Start Messaging button).
  • Added integration: after LoginActivity is created, the runtime now:
    1. Injects phone number '+15551234567' into PhoneView$3 (phoneField EditText) via dispatch_text_input_by_class.
    2. Dispatches click on FragmentFloatingButton (Next button) via dispatch_click_by_class.
  • The click reaches the REAL Telegram callback path:
    • Listener class: LoginActivity$$ExternalSyntheticLambda3 (lambda/synthetic class)
    • Callback method: onClick(View) dispatched via try_recursive_invoke
    • onNextPressed called 10 times (real DEX bytecode executed)
    • ConnectionsManager.sendRequest called (auth.sendCode network boundary reached)

Interaction trace

[UI-EVENT] event=TEXT_INPUT view_object=2827 view_class=Lorg/telegram/ui/LoginActivity$PhoneView$3 old_text="" new_text="+15551234567"
[UI-EVENT] event=TEXT_INPUT result=DISPATCHED view=2827 text="+15551234567"
[EXP069] Text input result: DISPATCHED
[EXP069] Phase 6: Clicking FragmentFloatingButton...
[UI-EVENT] event=CLICK view_object=3869 view_class=Lorg/telegram/ui/Components/FragmentFloatingButton listener=3897 listener_class=Lorg/telegram/ui/LoginActivity$$ExternalSyntheticLambda3
[UI-EVENT] event=CLICK result=DISPATCHED listener=Lorg/telegram/ui/LoginActivity$$ExternalSyntheticLambda3
[EXP069] Click result: DISPATCHED

Generic impact:

  • dispatch_text_input is GENERIC — it dispatches to ViewShadow.setText, which is the same path DEX bytecode uses. Any Android app's EditText can receive text input this way.
  • dispatch_click is GENERIC — it invokes the real OnClickListener.onClick(View) via try_recursive_invoke, which executes the real DEX bytecode of the listener's class (including synthetic/lambda classes).
  • The interaction flow (text input → click → callback → network boundary) is a generic Android interaction pattern, not Telegram-specific.

Tests:

  • 3-run reproducibility: identical SHA256 (064b82f2582faf7624f9a6d8f755bee48c4d4d78be115a81fe62fd7e055b1ead)
  • Generic regression (synthetic Acme app): PASS — match_rate=1.0
  • OCR: all 3 expected strings detected (Please confirm..., Phone number, Country)
  • Phone field text verified in view_tree.json: '+15551234567'
  • onNextPressed called 10 times (real DEX bytecode executed)
  • ConnectionsManager.sendRequest called (auth.sendCode boundary reached)

Before/after:

Before (EXP-068) After (EXP-069)
Text input not possible phone number injected
Click on Next not possible click dispatched to real listener
onNextPressed not called called 10 times
sendRequest not called called (auth.sendCode boundary)
Phone field text empty '+15551234567'
login_ui.png static screenshot shows injected phone number

Memory:
Runtime RSS ~519 MB (unchanged). The interaction subsystem adds negligible memory (just the dispatch methods, no new data structures).

Image result:
The login_ui.png now shows the phone number +15551234567 rendered in the phone field (previously empty). The image is 27KB (was 22KB — the additional text content increases the PNG size).

Checkpoint:
CHECKPOINT_L_LOGIN_UI = PROVEN (maintained, with interactive text input + click dispatch)

Network boundary status (STUB_DEBT):

  • ConnectionsManager.sendRequest is called by the real onNextPressed bytecode
  • The native network call (native_sendRequest) is STUBBED — no real Telegram server request
  • The RequestDelegate callback does NOT fire because no response is returned
  • This is the controlled network boundary (Phase 11 — TODO)
  • Classification: CONTROLLED_NETWORK_STUB — NOT real Telegram networking

Remaining blockers:

  • Controlled mock network response (Phase 11/12/13) — intercept sendRequest, produce mock TL_auth_sentCode, deliver through real RequestDelegate callback
  • Page state transition (Phase 14) — setPage(VIEW_CODE_SMS) not yet reached
  • SMS View discovery (Phase 15) — SmsView not yet visible
  • SMS screenshot (Phase 18) — login_sms.png not yet generated
  • TextWatcher callback dispatch (Phase 3) — not yet implemented
  • Real measure/layout engine (Phase 2 from EXP-068 spec)

Final commit: fd95856EXP-069 Phase 2+6: Generic text input + click dispatch

The image is the gate. The pixels show the injected phone number. The click reached the real callback path (onNextPressed → sendRequest). ✅

STUB_DEBT:

  • NETWORK: controlled auth.sendCode response — NOT real Telegram server communication
  • NATIVE: native_sendRequest stubbed — no real MTProto
  • THREAD: deterministic main-thread model — not full Android scheduling

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions