Files
file-manager/docs/EDGE_CASE_TESTING.md
T
SoftwareApp 667a85f80c Remember what is in the trash, and add a screen to restore from it
The staged-delete work left a hole. The undo handle lived in BrowserUiState, so a delete from an earlier session was unreachable even though the files were sitting on the volume; and because nothing on disk recorded which folder an item came from, not even the user could put one back by hand with confidence. Adding a Trash screen alone would not have fixed it: the recovery data did not survive the process. So the origin is now written at delete time.

data/ gains its first persistence: a SQLite index (staged path, original path, name, type, size, timestamp). SQLite rather than Room because an annotation processor is a large addition to this build for one table and three queries, and behind a TrashIndex port so domain/Trash keeps no Context while the tests drive it with a map and the real one is still tested against real SQLite. New Trash entry in the overflow menu lists batches and restores a whole one.

The index is an index, not the truth: the staged files are the truth, and the two can disagree if a user empties the folder by hand or pulls a card. Reconciled both ways - restorableFrom drops entries whose file has gone, purgeExpired forgets entries whose folder has gone and sweeps folders no entry mentions - and rows are written after the move, so a crash leaves an unindexed folder (harmless, swept) rather than an entry that could never restore. Verified on hardware: delete, force-stop, relaunch, restore.

Also corrects the docs where they claimed input swipe x y x y 900 is delivered as a plain tap on MIUI. It does open the selection bar - it was driven that way - but it has also landed as a tap, so it is flaky rather than impossible.
2026-10-15 10:25:37 +02:00

66 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# On-device testing
What has actually been run on hardware, what it found, and what is still unverified. Keep
this file honest: an untested claim is a bug waiting to be reported.
## Devices used
| Device | Android | Notes |
|---|---|---|
| Xiaomi **M2101K7AG** (Redmi, `sunny`), MIUI V140 | 12 (API 31), arm64-v8a | A real phone with a real 55 GB library. Auto-rotate was on, so runs happened in both orientations. |
| AOSP `phone` AVD | 12 (API 31), x86_64 | Software emulation — the host exposes no `/dev/kvm`. Used from M0–M6. |
Connecting a phone to this dev container needs one fix: the USB node is created
`root:plugdev 0660`, and the container's user is not in `plugdev`, so adb cannot open it.
An udev rule widening the mode for Android vendors fixes it
(`/etc/udev/rules.d/51-android.rules`), after which `adb devices` sees the phone.
## Verified on the real device
| What | Result |
|---|---|
| First run, no permission granted | The "Choose a folder" prompt appears with both routes offered: *Grant full access* and *Choose folder*. Correct — the app has no source yet, so the SAF fallback is the honest state. |
| Granting "All files access" while the app is alive | The app picks it up on resume and switches from the prompt to the roots view, showing **"Internal storage · 50.0 GB free"** (matching `df`). The lifecycle refresh works. |
| Browsing real storage | Real folders listed alphabetically with correct icons and breadcrumbs ("Internal storage / Download"). Titles render "Internal storage", not the raw volume name. |
| Text editor, read | Tapping `a.txt` opened the editor showing its real content. |
| Text editor, **write** | Editing and tapping Save persisted to the device — verified independently with `adb shell cat`. |
| Storage usage | DCIM 2.7 GB / 668 files, Android 1.2 GB / 5925 files, Music 1.2 GB / 43 files, Pictures 866.4 MB / 5849 files, … sorted largest first with per-row share bars and correct plurals. |
| Revoking "All files access" mid-use | Returned to the folder prompt without crashing; the app kept running. Graceful degradation confirmed. |
| Landscape | The whole UI adapts (the phone auto-rotated mid-session): app bar, list, breadcrumbs and dialogs all laid out correctly. |
| `BACK` from the roots view | Exits the app, which is the expected Android behaviour. |
## Bugs this session found — both fixed
1. **The first-run copy was wrong.** The prompt read *"Full access was declined, so pick a
folder…"* on a device where the user had never declined anything. Reworded to
*"Without full access you can still work inside one folder you choose here."*, which is
true whether the user declined or simply has not granted yet. Re-verified on device.
2. **The storage-usage screen took ~45–60 seconds to show anything.** Measuring the root of
a real 55 GB volume blocked on the whole walk with only a spinner for company, which
reads as a hang. Two changes:
- `UsageAnalysis` now passes the `FileEntry` down the recursion instead of re-`stat`ing
every node (the parent's listing already says whether each child is a folder), so the
walk costs one listing per directory and nothing more.
- Rows are **published as they are measured** through an `onProgress` callback, and the
ViewModel appends them, re-sorting as it goes, so the biggest folders appear while the
rest of the tree is still being walked.
The UI never froze — the progress bar kept animating throughout, which confirms the I/O
stays off the main thread — but "slow and silent" is still a defect.
## Not verified, and why
- **Long-press multi-select via adb: it works, but not every time.** `input swipe x y x y 900`
*does* open the selection action bar on this MIUI build — it was driven that way to reach
Delete, Rename and Compress — but the same gesture has also landed as a plain tap, which
opens the row instead of selecting it. So the bar is reachable from the host, and yet
compress/extract from the UI is still worth a manual pass rather than trusted to a scripted
gesture. The archive engine itself is covered by end-to-end JVM tests, including a zip-slip
archive.
- **The SAF folder-picker round trip.** Driving the system picker and granting a tree was
not attempted; the code path is unit-tested against a stand-in `DocumentsProvider`.
- **Image viewer and thumbnails.** Verified on the AVD in M4/M5; not repeated on the phone.
- **The foreground-service notification** during a long copy. Started in M3 and unit-tested;
not observed on hardware.
- **Archive creation/extraction against real files.** Only exercised in-memory.