Skip to content

Commit 286d280

Browse files
committed
[docs] record Android recovery and app-only matrix acceptance
Signed-off-by: Viwat Vchirawongkwin <viwat.v@chula.ac.th>
1 parent 758030a commit 286d280

1 file changed

Lines changed: 127 additions & 0 deletions

File tree

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<!-- SPDX-License-Identifier: MIT -->
2+
<!-- Part of PyBLE (https://pyble.dev) — see /LICENSE. -->
3+
4+
# Android recovery acceptance continuation
5+
6+
| Field | Record |
7+
|---|---|
8+
| Date / operator | 31 October 2026; automated operator on the maintainer's Mac |
9+
| State | Completed Android continuation within the physical scope and limitations recorded below |
10+
| Physical device | Lenovo TB-J616X; Android 12 / API 31; landscape 2000 × 1200 pixels at 240 dpi |
11+
| App | `0.3.0 (9)`, normal `lib/main.dart`; isolated qualification application identity preserves the installed store app and its data |
12+
| Final runtime source | `01a7ac8acab32e926c185c8567f9b8dca08d3d68`; Android worktree runtime is byte-equivalent. The native package name alone is changed for the isolated identity |
13+
| Final profile APK SHA-256 | `afc50a741a07344047d3069c9d4a36c1111869b3286e67b0a9f8d4a61a408e89`; also verified against the installed `base.apk` |
14+
| Final arm64 AOT SHA-256 | `2ddb34eb36169466b5aa5aa32515e007354389f1ebdd276c0fdd40638e6e47a4` |
15+
| Final native DEX SHA-256 | `1b62aceb530a2d361980b18d009188994cf7c92118d22842af3a6293757b61bb` |
16+
| Original debug APK | Source equivalent to `6f5b3ea`; SHA-256 `957982f5acec969f8003d04b2d6444eecbba9af26b7392d760badb5be5d6bd0e`; original failures retained |
17+
| Earlier profile APK | Runtime equivalent to `e54a78a`; SHA-256 `5b93b0c68bfc7bfa06a3a887ab70192a4d47c4786cf82e5428005ef94b199861` |
18+
| Governing evidence | [Recovery contract](../../../specifications/App/current-draft-recovery.md#7-required-evidence-before-acceptance), [operator recipe](01_Operator_Recipe.md), [execution record](00_Execution_Record.md), [release matrix](../c1-s1/04_Release_Qualification_Matrix.md) |
19+
| Private evidence | Ignored `local/recovery-completion/android/`: exact artifact/source manifests, native assertions, fresh UI XML/screenshots, logs, initial isolated-data backup and installed-artifact hash |
20+
21+
Both profile candidates were built from the normal application entry point.
22+
The final candidate was built after `flutter clean`, with the new Dart keyboard
23+
helper and native activity handler included. It is a qualification package;
24+
these observations do not independently establish Play delivery or production
25+
signing. The release record owns that separate packaging evidence.
26+
27+
## Recovery and replacement observations
28+
29+
The initial isolated Editor was empty. Its private data was backed up before
30+
qualification, and the store app was not replaced or cleared. Only disposable
31+
text and uniquely named board fixtures were used. No firmware was flashed by
32+
this Android workflow.
33+
34+
| Recipe | Result / physical oracle | Evidence prefix |
35+
|---|---|---|
36+
| P01 | Pass on final candidate: actual Bluetooth state OFF and Wi-Fi disabled; startup presents the exact checkpoint before any connection workflow | `nativefix-all-offline-relaunch`, `nativefix-offline-bluetooth-confirmed` |
37+
| P02 | Pass: named `recovery.py` retains Unicode `✓`, punctuation, blank lines and final newline; native entry was asserted exactly before normal key-event editing | `nativefix-typing-seed`, `nativefix-continuous-expected` |
38+
| P03 | Pass: explicit recovery save acknowledges the matching text; Saved locally and board Unsaved changes remain distinct | `profile-saved-local`, `nativefix-continuous-saved` |
39+
| P04 | Pass: actual force-stop/relaunch reproduces exact named text and checkpoint, including the generated Blocks text | `nativefix-typed-offline-relaunch`, `nativefix-generated-relaunch` |
40+
| P05 | Pass: Back leaves the unresolved recovery decision; relaunch presents the same complete generated checkpoint | `nativefix-recovery-before-back`, `nativefix-recovery-after-back` |
41+
| P06 | Pass on final candidate: explicit Restore shows exact text in the disconnected local panel; connecting remains a separate action | `controlled-3dcb-local-restore` |
42+
| P07 | Pass for ordinary edit/lifecycle behavior: repeated normal key events, idle acknowledged checkpoint, backgrounding, force-stop and exact recovery | `nativefix-continuous-*`, `nativefix-all-offline-relaunch` |
43+
| P08 | Pass on final candidate: Cancel retains the exact copy; confirmed Discard commits the empty slot and another process launch has no recovery prompt | `controlled-3dcb-discard-*`, `controlled-3dcb-empty-slot` |
44+
| P09 | Pass on earlier profile: deliberately empty named `acceptance_1730.py` survives checkpoint/process relaunch as a recoverable document | `profile-empty-named-saved`, `profile-empty-named-prompt` |
45+
| P10 | Pass on earlier profile: Save and Run show their current destination and distinct write-only/write-and-run effects; Cancel preserves the document. Confirmed upload and subsequent Run produced `67891` | `profile-save-consent-dialog`, `profile-run-consent-dialog`, `profile-named-upload-consent`, `profile-hello-output-complete` |
46+
| P11 | Pass for physical moved-directory destination: Upload names the actual current directory; cancellation and confirmed upload were exercised | `profile-upload-cwd-consent`, `controlled-3dcb-cwd-upload-consent` |
47+
| P12 | Pass on final candidate: matching confirmed upload clears board dirty; a new connection session requires current-target consent again, which was cancelled | `controlled-3dcb-upload-ack`, `controlled-3dcb-new-session-consent` |
48+
| P13 | Pass on final candidate: Editor New, Board Open and Blocks handoff each protect meaningful pending Unicode text. Cancel retains it exactly; confirmed Blocks replacement installs the generated text | `nativefix-new-*`, `nativefix-board-open-*`, `nativefix-block-handoff-*` |
49+
| P14 / DR-T12 | Pass on final candidate: normal Hello example → Open in Editor → guarded replacement → Save recovery copy → Disconnect → force-stop/relaunch recovers exactly `print('Hello, PyBLE!')\n` as text | `nativefix-generated-checkpoint`, `nativefix-generated-relaunch` |
50+
| P15 | Verified physical scope: 2× recovery controls, Editor/Blocks keyboard layout, and native accessibility focus/labels with TalkBack active. Audible pronunciation and complete gesture navigation were not observed | `nativefix-named-2x-*`, `nativefix-blocks-ime-*`, `talkback-probe-*` |
51+
52+
The generated-text recovery observation does not claim restoration of a Blocks
53+
workspace, revision history or companion files. The UI explicitly states that
54+
the local slot contains one current text draft.
55+
56+
The retained earlier-profile observations cover unchanged storage, target-guard
57+
and transport code. The final runtime changes keyboard dismissal; its affected
58+
Editor/native-WebView behavior and Blocks handoff were repeated on the final
59+
installed artifact. This is an impact assessment, not a claim that every earlier
60+
observation was rerun on identical bytes.
61+
62+
Deterministic transaction-phase interruption, storage failure/volatile fallback
63+
and stale-consent races remain covered by the automated fault/controller tests.
64+
The normal device UI does not provide a reliable way to force those internal
65+
phases. Their physical execution is not inferred from a successful ordinary
66+
restart. Error-panel localization/layout coverage also remains part of the
67+
host widget/semantics/golden evidence.
68+
69+
## Physical app-only matrix
70+
71+
Every passing core row covers edit, explicit Save, Run, observed stdout, Stop,
72+
clearing the Editor before opening the saved board file, exact readback, explicit
73+
disconnect/reconnect, and another readback. Program bytes and private action
74+
receipts are retained with each row. A Ready scan result alone is not counted.
75+
76+
| Row | Exact profile / board alias | App candidate | Result | Raw prefix |
77+
|---|---|---|---|---|
78+
| Q02 | `esp32-4mb` / 8C9E | Final | Pass | `q8c9e` |
79+
| Q04 | `esp32-s3-n16r8` / 5646 | Final | Pass | `q5646` |
80+
| Q06 | `waveshare-esp32-s3-lcd-147b` / DA86 | Final | Pass | `qda86` |
81+
| Q08 | `esp32-c3-4mb` / C81A | Earlier profile; unchanged transport/run code | Pass, including both required real-UI Stop cases | `profile-c3-*`, `profile-tight-*`, `profile-flood-*` |
82+
| Q10 | `rpi-pico2-w` / 3DCB | Final | Pass after an explicitly retained Android-133 connection failure and retry | `q3dcb` |
83+
84+
C3 ran both `while True:\n pass\n` and
85+
`while True:\n print(24680)\n`. The recorded UI changed from Running to
86+
Ready/Console Idle after Stop and remained connected. During the print flood,
87+
UIAutomator could not obtain an idle hierarchy; a direct live screenshot records
88+
Running and repeated output before the captured toolbar Stop action. The settled
89+
hierarchy then records Ready/Idle. No fresh wire-level latency bound or complete
90+
firmware C3 qualification is claimed.
91+
92+
The [execution record](00_Execution_Record.md) owns the fresh immutable-program
93+
bindings and app-only scope decision. Classic ESP32 is bound to the published
94+
baseline; the two S3 boards, C3 and Pico 2 W are bound to the verified observer
95+
baseline `96497b9`. Their common HELLO version `0.6.1` is not treated as evidence
96+
of identical firmware bytes or of the published five-profile firmware gate.
97+
98+
## Defects resolved and evidence limits
99+
100+
| Finding | Original observation | Final observation |
101+
|---|---|---|
102+
| Landscape keyboard overflow | Original debug candidate hid the Editor and overflowed Files/navigation while IME was visible | Editor and navigation remain visible; console collapses honestly and expands after keyboard dismissal |
103+
| Native WebView keyboard remained open | Earlier profile: Blocks HTML field → Expand console retained the IME despite the successful semantic button action | Final profile: same action retains the field/workspace, expands console, and changes Android `mInputShown` from true to false |
104+
| Initial debug Blocks startup failure | Original debug retries and device/provider restart reached the startup watchdog; browser-side diagnostics alone did not establish a JS/CSP cause | Clean profile application initializes, loads/edits the example and completes real handoff/relaunch. Exact-assets native and pinned-plugin diagnostic apps also initialize. No speculative CSP/bootstrap change was made |
105+
106+
Initial helper attempts that reused a stale hierarchy, replaced populated rich
107+
Editor text unreliably, or encountered an unrelated Android crash dialog were
108+
retained and excluded. Accepted readbacks first clear the Editor, and named-file
109+
input waits for the adopted Editor filename. The initial TalkBack gesture
110+
attempt is also excluded because service/interaction state was not controlled.
111+
A post-probe interval failed the following test's expected UI precondition and
112+
was excluded from target/discard acceptance; that complete sequence subsequently
113+
passed in a fresh uninterrupted run. No cause is inferred for those intervals.
114+
115+
The later isolated accessibility probe used
116+
`FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES`. For Restore, Copy text and Discard
117+
recovery copy, it verified an exact visible/enabled native button, accepted
118+
accessibility-focus action, matching focus event and focused node. TalkBack
119+
remained bound before and after the probes. This verifies native focus and label
120+
exposure, not audible speech or complete screen-reader usability. Recorded
121+
accessibility-service, touch-exploration and font settings were restored in a
122+
`finally` step. Original radio settings were restored after offline checks.
123+
All board connections were explicitly released; temporary diagnostic apps,
124+
device helper files and the debugging forward were removed. The isolated
125+
qualification app/data and private evidence remain available for review. An
126+
exact ownership manifest records the disposable board fixtures for coordinated
127+
cleanup without touching other files.

0 commit comments

Comments
 (0)