Skip to content

add GosCompatWebViewUaStartupTests and GosCompatDmaBufReleaseTests#355

Open
inthewaves wants to merge 2 commits into
GrapheneOS:16-qpr2from
inthewaves:more-goscompat-tests
Open

add GosCompatWebViewUaStartupTests and GosCompatDmaBufReleaseTests#355
inthewaves wants to merge 2 commits into
GrapheneOS:16-qpr2from
inthewaves:more-goscompat-tests

Conversation

@inthewaves
Copy link
Copy Markdown
Member

Kernel patch for the panic in the DmaBufRelease tests is at https://gitlab.com/grapheneos/kernel_pixel_muzel/-/merge_requests/8

GosCompatWebViewUaStartupTests

See GrapheneOS/os-issue-tracker#7829 (comment)

GosCompatWebViewUaStartupTests covers WebView default user agent startup when an app worker thread holds an app lock and the app UI thread is blocked trying to acquire the same lock on the Android
main looper. It relaunches the helper app process for each attempt so
WebSettings.getDefaultUserAgent() is exercised from a fresh app start.

This is especially evident with apps not following recommended practices for Google Mobile Ads SDK.
For example, an app can call this on the main thread:

new AdLoader.Builder(context, adUnitId)
        .forNativeAd(nativeAdLoadedListener)
        .withNativeAdOptions(nativeAdOptions)
        .withAdListener(adListener)
        .build() // This causes the deadlock since this is on main thread
        .loadAd(adRequest);

Google recommends to only call AdLoader.Builder from a worker thread 1. However, not all apps
follow these recommendations. The nuance is that loadAd can only be called on the main thread, but
the creation of the AdLoader should be done on a worker thread.

During app startup, a worker thread in the Mobile Ads SDK holds a singleton lock and calls
WebSettings.getDefaultUserAgent(). When the WebViewFasterGetDefaultUserAgent feature for WebView
is disabled, this blocks the worker thread until its task posted to the main thread to initialize
WebView finishes.

Meanwhile, the main thread of the app enters Mobile Ads SDK by the function calls above. Inside of
AdLoader.Builder#build, if the Dynamite ads module is not available, the library has a local
fallback path which attempts to acquires the singleton lock that the worker thread is holding. The
result is that the main thread gets blocked on a lock held by the worker thread which is waiting for
main thread to process its task.

Dynamite ads module can be unavailable if Play services + Play Store are not installed (or have some
other issue). This would block users from using any app with SDK used in this way.

By enabling WebViewFasterGetDefaultUserAgent, the worker thread no longer waits on the
initialization task posted to main thread to finish and gets a user agent immediately. This works
around this deadlock.

GosCompatDmaBufReleaseTests

See GrapheneOS/os-issue-tracker#7347

This module is a targeted regression test for a 10th-gen Pixel kernel memory error in the Samsung
DMA-BUF secure chunk heap release path.

The tests will panic on a kernel without the patch for the memory error. Note that these tests are
designed to be non-priv apps.

Access rules

The helper app intentionally opens the heap devices directly. This is allowed by the device policy
and file modes:

  • vendor/etc/ueventd.rc sets both heap devices to mode 0444.
  • Vendor SEPolicy labels both devices as dmabuf_system_secure_heap_device.
  • system/sepolicy/private/app.te allows non-isolated app domains to read and open
    dmabuf_system_secure_heap_device character devices.

The native helper only accepts the allowlisted heap names above. It does not use the intent extra as
an arbitrary file path.

Relationship to existing AOSP tests

The native helper follows the same basic allocation and release pattern as the existing DMA-BUF heap
unit tests:

  • system/memory/libdmabufheap/tests/dmabuf_heap_test.cpp: DmaBufHeapTest.Allocate allocates
    DMA-BUF fds and closes them to release the buffers.
  • system/memory/libdmabufheap/tests/dmabuf_heap_test.cpp: DmaBufHeapTest.RepeatedAllocate
    repeats the same allocate and close path.
  • system/memory/libdmabufheap/tests/dmabuf_heap_test.c: libdmabufheaptest() exercises the C
    wrapper around the same libdmabufheap allocation flow.

Note that these tests did not panic. In general, CTS tests in AOSP don't exercise these
Pixel-specific paths or they don't test process teardown.

This helper intentionally does not link libdmabufheap, because it is built inside the SDK-built
helper APK and needs to target Pixel secure heap device names directly. Instead, it opens
/dev/dma_heap/vframe-secure or /dev/dma_heap/vstream-secure and issues DMA_HEAP_IOCTL_ALLOC,
then either closes the returned fd during manual release or leaves it open until process teardown
closes it.

The protected EGL tests uses the public EGL/GLES shape that is closest to the PowerVR usage: EGL_EXT_protected_content on a protected context and pbuffer surface, plus
GL_EXT_protected_textures for protected texture storage. It then keeps the helper process alive
until the instrumentation test force stops it.

Footnotes

  1. https://developers.google.com/admob/android/native#build

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant