fix(adb): keep a bare numeric wm density as the physical density (#4074)

Older Android builds print `wm density` as a bare number. The parser's
documentation named that form, but only the labeled `Physical density:`
and `Override density:` lines were matched, so a bare `420` left
`physical_density` null in successful display Evidence with no limitation
saying the declaration was unread (#3942).

The parser now reads the first bare numeric line as the physical density
when no labeled physical declaration is present; a labeled declaration
still wins so a mixed dump cannot downgrade the value. Override density
and physical size are unchanged.

Validation: parser unit tests for the labeled, bare, CRLF, mixed and
unrecognized forms, plus a provider-level regression through the
inspect_adb_display operation; two of them fail on main and pass here.
The issue's three CLI controls through `rea inspect-adb-display` against
a stub adb return physical density 420 for the bare form and keep the
labeled and override controls. Typecheck, lint and module boundaries pass.

Closes #3942
This commit is contained in:
Yankı Küçük authored and GitHub committed 2026-10-17 00:15:05 +08:00
1 parent e0b989cc0a
commit bef3fbbc6e
3 files changed
+75 -3

No files matched your search

+20
View File
@@ -1280,6 +1280,26 @@ it("inspects the display and window focus", async () => {
);
});
// Older builds print `wm density` as a bare number; the display projection
// must keep it as the physical density (morluto/rea#3942).
it("keeps a bare numeric wm density as the physical density", async () => {
const { binary } = await writeAdbStub(
shellStub({
"wm:size": "Physical size: 1080x2340\n",
"wm:density": "420\n",
}),
);
const display = await evidenceResult(providerOver(binary), {
operation: "inspect_adb_display",
input: { serial: "emulator-5554" },
});
expect(display).toMatchObject({
physical_size: { width: 1080, height: 2340 },
physical_density: 420,
override_density: null,
});
});
it("reads Android 16 focus declarations from displays when windows omits them", async () => {
const { binary } = await writeAdbStub(
shellStub({
+44 -1
View File
@@ -1,6 +1,49 @@
import { describe, expect, it } from "vitest";
import { parseAmStartOutput } from "./AdbShellOutput.js";
import { parseAmStartOutput, parseWmDensityOutput } from "./AdbShellOutput.js";
describe("parseWmDensityOutput", () => {
it("reads labeled physical and override densities", () => {
expect(
parseWmDensityOutput("Physical density: 420\nOverride density: 480\n"),
).toEqual({ physical: 420, override: 480 });
expect(parseWmDensityOutput("Physical density: 420\n")).toEqual({
physical: 420,
override: null,
});
});
// Older builds print the physical density as a bare number
// (morluto/rea#3942); it must not be lost as an unread declaration.
it("reads a bare numeric density as the physical density", () => {
expect(parseWmDensityOutput("420\n")).toEqual({
physical: 420,
override: null,
});
expect(parseWmDensityOutput("420\r\n")).toEqual({
physical: 420,
override: null,
});
});
it("prefers a labeled physical density over a bare number", () => {
expect(parseWmDensityOutput("560\nPhysical density: 420\n")).toEqual({
physical: 420,
override: null,
});
});
it("reports no density for unrecognized output", () => {
expect(parseWmDensityOutput("")).toEqual({
physical: null,
override: null,
});
expect(parseWmDensityOutput("420dpi\n")).toEqual({
physical: null,
override: null,
});
});
});
const starting =
"Starting: Intent { act=android.intent.action.MAIN cmp=com.example/.Main }";
+11 -2
View File
@@ -125,6 +125,7 @@ const SIZE_PAIR = /^Physical size:\s+(\d+)x(\d+)$/u;
const SIZE_OVERRIDE = /^Override size:\s+(\d+)x(\d+)$/u;
const DENSITY_PHYSICAL = /^Physical density:\s+(\d+)$/u;
const DENSITY_OVERRIDE = /^Override density:\s+(\d+)$/u;
const DENSITY_BARE = /^(\d+)$/u;
/** Parse `wm size` output into physical and optional override sizes. */
export const parseWmSizeOutput = (
@@ -153,7 +154,12 @@ export const parseWmSizeOutput = (
return { physical, override };
};
/** Parse `wm density` output. Older builds print a bare number. */
/**
* Parse `wm density` output. Current builds print labeled physical and
* optional override lines; older builds print the physical density as a
* bare number on its own line (morluto/rea#3942). A labeled declaration
* wins over a bare one so a mixed dump cannot downgrade the physical value.
*/
export const parseWmDensityOutput = (
stdout: string,
): {
@@ -162,14 +168,17 @@ export const parseWmDensityOutput = (
} => {
let physical = null;
let override = null;
let bare = null;
for (const line of stdout.split(/\r?\n/u)) {
const trimmed = line.trim();
const physicalMatch = DENSITY_PHYSICAL.exec(trimmed);
if (physicalMatch !== null) physical = Number(physicalMatch[1]!);
const overrideMatch = DENSITY_OVERRIDE.exec(trimmed);
if (overrideMatch !== null) override = Number(overrideMatch[1]!);
const bareMatch = DENSITY_BARE.exec(trimmed);
if (bareMatch !== null && bare === null) bare = Number(bareMatch[1]!);
}
return { physical, override };
return { physical: physical ?? bare, override };
};
/** Parse focus declarations from `dumpsys window windows` or `displays`. */