Skip to content

Android: window geometry reporter misses two spec requirements (view-bounds sandboxing property; first-SurfaceView lookup) #195

Description

@dfattal

Two latent defects in the Android window-geometry reporter (patch 0123, DisplayXrWindowGeometry.java), found while diagnosing raw-SBS-in-fullscreen on the gallery. Neither is confirmed as the cause of that symptom (tracked separately once the device test discriminates browser vs gallery); both are spec/robustness gaps on their own.

1. Manifest does not opt out of view-bounds sandboxing

The runtime spec XR_DXR_android_surface_binding.md §4 (docs/specs/extensions/, runtime repo, line ~199) requires the app manifest to declare:

<property android:name="android.window.PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS"
          android:value="false" />

The patch series (patches/, docs, scripts) contains no such property. Under OEM view-bounds sandboxing (Android 14+ compat behaviour), View.getLocationOnScreen() becomes window-relative, so the reporter's content.getLocationOnScreen(mLoc) (0123:318) silently publishes (0,0) for every window — indistinguishable from a window parked at the display origin. Reproduction depends on the OEM/ROM; the failure is silent by construction.

Fix: add the property to the browser's manifest patch (and note it in docs/integration-points.md as a rebase-stable file).

2. findSurfaceView() returns the first SurfaceView in hierarchy order

private static @Nullable View findSurfaceView(View v) {
    if (v instanceof SurfaceView) return v;
    ...depth-first, first match wins

(0123:369-377). Chromium's CompositorSurfaceManager keeps two SurfaceViews (opaque and translucent) and swaps the live one on a pixel-format change. After a swap the stale view is still attached and still reports a non-zero size, so the getWidth()==0 || getHeight()==0 guard at 0123:317 does not catch it, and geometry can be read from the wrong surface. A fullscreen transition is one of the events that can trigger a format swap.

Fix: resolve the surface the compositor is actually presenting to (e.g. via CompositorSurfaceManager's current view / the SurfaceHolder the Surface was created from) rather than hierarchy order, or at minimum prefer the view whose getHolder().getSurface().isValid() and that matches the surface handed to the runtime.

Environment

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions