mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 18:47:04 +01:00
android_ui: never check or dismiss the keyboard on a virtual display
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (mypy, mypy) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (pylint, pylint) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (rest, ) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (shellcheck, shellcheck) (push) Waiting to run
Python tests / test (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / lib-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (mypy, mypy) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (pylint, pylint) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (rest, ) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (shellcheck, shellcheck) (push) Waiting to run
Python tests / test (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / lib-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
keyboard_is_up read the phone-wide mInputShown, but Android draws the IME on display 0 even when its target window is on a virtual display, so it can never cover a VD tap. With two sessions on one phone, the other session's keyboard on the real screen made dismiss_keyboard press BACK on this display, popping the route under test and then closing the app. Prunes the oldest evidence artifact to stay under the 60-file cap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KeVXsWTuwjmZK5uvbw6vqF
This commit is contained in:
parent
146726b9d4
commit
375555fa37
@ -0,0 +1,40 @@
|
||||
{
|
||||
"intent": "Two Claude sessions sharing one phone must not disturb each other: a keyboard open on the real screen must never make android_ui press BACK on another session's virtual display.",
|
||||
"scope": [
|
||||
"python_pkg/android_ui/_text_entry.py (keyboard_is_up only)",
|
||||
"Non-goal: no change to real-screen (display 0 / no display) behaviour, which still checks and dismisses the IME"
|
||||
],
|
||||
"changes": [
|
||||
"keyboard_is_up returns False when the driver targets a virtual display (display not None and not 0), so dismiss_keyboard sends no ESCAPE/BACK there",
|
||||
"Test: a VD driver with the phone-wide keyboard shown runs no adb command at all"
|
||||
],
|
||||
"verification": [
|
||||
{
|
||||
"command": "adb shell dumpsys input_method (live phone, 2026-09-27)",
|
||||
"result": "pass",
|
||||
"evidence": "every IME binding reads imeDisplayId=0, including one whose targetWin was com.kuhy.workout_app.sandbox on targetDisplayId=13: the IME is drawn on display 0 for VD windows"
|
||||
},
|
||||
{
|
||||
"command": "python -m python_pkg.android_ui --display self tap ... (before the fix, while another session typed on the real screen)",
|
||||
"result": "fail",
|
||||
"evidence": "'the soft keyboard is still covering the screen after ESCAPE and BACK'; the BACK popped the workout route, a second run closed the app on the VD"
|
||||
},
|
||||
{
|
||||
"command": "same taps after the fix",
|
||||
"result": "pass",
|
||||
"evidence": "tapped 'Dumbbell Lunge progression settings' / 'Warmup set' / 'Wins needed down' on the VD with the other session still active"
|
||||
},
|
||||
{
|
||||
"command": "pytest python_pkg/android_ui --cov=python_pkg/android_ui --cov-branch",
|
||||
"result": "pass",
|
||||
"evidence": "87 passed; _text_entry.py 100% lines and branches"
|
||||
}
|
||||
],
|
||||
"risks": [
|
||||
"A future Android build that draws the IME on the VD itself would make taps under it land on keys; the phone would have to show imeDisplayId=<vd> for that, which it does not today"
|
||||
],
|
||||
"rollback": [
|
||||
"git revert this commit",
|
||||
"After rollback, VD taps work again only while no other session has a keyboard open on the real screen"
|
||||
]
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
{
|
||||
"intent": "Remove nvidia_config.sh's coverage exemption, which was reinstated when an earlier commit's allowlist deletion did not survive alongside the seam restore.",
|
||||
"scope": [
|
||||
"meta/shell-coverage-allowlist.txt (one line removed)",
|
||||
"Non-goal: any code change; the lib and its tests are already correct"
|
||||
],
|
||||
"changes": [
|
||||
"Deleted the fixes/lib/nvidia_config.sh line from the allowlist, taking it from 85 to 84 entries"
|
||||
],
|
||||
"verification": [
|
||||
{
|
||||
"command": "shell_coverage_jail.sh with the gate's own flags (--bind /etc --bind /usr/local/bin --bind /var/lib), in a detached worktree",
|
||||
"result": "pass",
|
||||
"evidence": "nvidia_config.sh: 76/76 lines = 100.00%."
|
||||
},
|
||||
{
|
||||
"command": "The same measurement in the main working tree",
|
||||
"result": "fail",
|
||||
"evidence": "'the subject modified the working tree; a write escaped the jail', listing python_pkg/endurain_import files another agent was editing concurrently. This is a false positive from the jail's tree fingerprint, which is why the real measurement was taken in an isolated worktree."
|
||||
},
|
||||
{
|
||||
"command": "grep for the four seams in nvidia_config.sh",
|
||||
"result": "pass",
|
||||
"evidence": "All four present at lines 26, 27, 60 and 85. An earlier `grep -c 'XORG_CONF:-'` returning 1 counted matching LINES, not seams, and briefly looked like a regression."
|
||||
}
|
||||
],
|
||||
"risks": [
|
||||
"The coverage gate cannot be trusted while another agent is writing to the same working tree; any measurement must be taken in a detached worktree or it may abort on their churn."
|
||||
],
|
||||
"rollback": [
|
||||
"Re-add the nvidia_config.sh line to meta/shell-coverage-allowlist.txt"
|
||||
]
|
||||
}
|
||||
@ -28,6 +28,7 @@ class TextEntryMixin(ABC):
|
||||
"""The text-entry half of :class:`~python_pkg.android_ui.driver.AndroidUi`."""
|
||||
|
||||
_settle: float
|
||||
_display: int | None
|
||||
|
||||
@abstractmethod
|
||||
def _run(self, *args: str, timeout: float = 30.0) -> str:
|
||||
@ -137,7 +138,17 @@ class TextEntryMixin(ABC):
|
||||
Without this, a caller cannot tell "the button is absent" from "the
|
||||
button is behind the keyboard", and the accessibility tree reports the
|
||||
button's laid-out position either way.
|
||||
|
||||
Always False on a virtual display: Android draws the IME on the
|
||||
default display (``imeDisplayId=0``) even when its target window is
|
||||
on a VD, so it can never cover a VD tap -- while ``mInputShown`` is
|
||||
phone-wide. Checking it there meant another session typing on the
|
||||
real screen made :meth:`dismiss_keyboard` press BACK on *this*
|
||||
display, popping the route under test (2026-09-27, two sessions on
|
||||
one phone).
|
||||
"""
|
||||
if self._display not in (None, 0):
|
||||
return False
|
||||
out = self._run("shell", "dumpsys", "input_method")
|
||||
match = re.search(r"mInputShown=(\w+)", out)
|
||||
return match is not None and match.group(1) == "true"
|
||||
|
||||
@ -98,6 +98,22 @@ class TestKeyboard:
|
||||
ui.device.keyboard_shown = False
|
||||
assert not ui.ui.keyboard_is_up()
|
||||
|
||||
def test_never_up_on_a_virtual_display(
|
||||
self, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
# The IME draws on display 0 even for a VD's window, so it cannot
|
||||
# cover a VD tap -- but mInputShown is phone-wide. Reading it there
|
||||
# let another session's keyboard make dismiss_keyboard press BACK on
|
||||
# this display and pop the route under test (2026-09-27).
|
||||
device = FakeDevice()
|
||||
device.keyboard_shown = True
|
||||
vd = drv.AndroidUi(settle_seconds=0.0, display=7)
|
||||
monkeypatch.setattr(vd, "_run", device.run)
|
||||
monkeypatch.setattr(f"{MOD}.time.sleep", lambda _s: None)
|
||||
assert not vd.keyboard_is_up()
|
||||
vd.dismiss_keyboard()
|
||||
assert device.calls == [], "no dumpsys, and above all no BACK"
|
||||
|
||||
def test_dismiss_is_a_no_op_when_already_closed(self, ui: Harness) -> None:
|
||||
ui.ui.dismiss_keyboard()
|
||||
assert not [
|
||||
|
||||
Loading…
Reference in New Issue
Block a user