Towards a GNOME Mobile Test Suite

And What’s Blocking Our Way

Photo of a OnePlus 6 running GNOME Shell Mobile and displaying the GNOME OS website in GNOME Web
mobile

GNOME Mobile

Making GNOME adapt to form factors beyond desktop and laptop computers is an ongoing trend that can be dated as early as the late 2000s, when Maemo provided a GNOME-based UI to phones like the Nokia N810 or the Nokia N900. Later, prototype versions of GNOME Shell had a netbook-friendly design that got course-corrected for its first release in 2011, keeping GNOME competent on larger screens.

GNOME 3 was designed with touchscreens in mind, especially touchscreen-equiped netbooks and laptops, with some foray into large touch-only devices like kiosks. With its touch-capabilities and minimalist touch-friendly design, GNOME 3 offered a good base to adapt to even smaller touch-only form factors like tablets and smartphones.

In the late 2010 two Linux smartphones got developed concurrently, Purism’s Librem 5 and Pine64’s PinePhone. Purism choose GNOME as the UI for its phone and invested in the development of the Phosh mobile-first shell for GNOME and into making GNOME apps adapt to smartphones. The GNOME community pretty widely embraced adaptiveness, which led to the creation of GNOME’s platform library libadwaita. At the same time, community-driven projects like postmarketOS and Mobian offered support for these smartphones and contributed to the development of this mobile-friendly software stack, including contributions to GNOME.

While these devices’ reception was polarizing, the Linux community was motivated enough to pursue what they initiated, leading to the birth of GNOME Shell Mobile and to the broadening of supported devices. While GNOME Shell got forked to make it fit smartphones, it is only to prototype this mobile support freely. Ultimately the goal is the this support into Shell, making it adapt from desktops to smartphones. This still overall prototypal support for modern smartphones from GNOME and the initiative that supports it are colloquially referred to as GNOME Mobile.

Testing GNOME Mobile

The GNOME release team defines what constitues the canonical core GNOME stack, and describes it in the gnome-build-meta repository. GNOME OS is built based on this description and is used to test GNOME, ensuring its components are correctly integrated and interact well together. openQA is a high-level and automated OS testing tool, and in 2021, Codethink brought GNOME an openQA instance that is used to test GNOME OS automatically rather than manually. The tests are ran in virtual machines thanks to QEMU.

Testing GNOME on smartphones implies testing its mobile-specific stack on smartphone-like devices the same way we test the rest of GNOME. Hardware requirements for GNOME are pretty loosely defined, and the only real requirement for smartphones is that apps designed for them should fit in a 360 × 294px window, so they can fit a 360px wide screen in portrait mode and a 360px tall screen in landscape mode, minus the space reserved for Shell. To that we can safely assume that a smartphone reports having a handset chassis type, that it has a touchscreen as its main input method, that it should work without a keyboard and a pointing device, that its screen is 9:16 or taller, and that the its has a high pixel density and should be used with an matching integer scaling factor. For reference, here is the pixel density of some de-facto reference GNOME smartphones.

Device Diagonal Resolution Density UI Scale
Librem 5 5.7” 720 × 1440px 282 ppi 200%
PinePhone 5.95” 720 × 1440px 270 ppi 200%
PinePhone Pro 6” 720 × 1440px 268 ppi 200%
OnePlus 6 6.28” 1080 × 2280px 401 ppi 300%
OnePlus 6T 6.41” 1080 × 2340px 402 ppi 300%

Building an automated test suite for GNOME Mobile in openQA has already been attempted earlier this year by Dorothy Kabarozi and Tanju Acheleke, and they built the gnome_mobile test suite. Last month I got offered by Codethink the opportunity to continue that effort, thanks to them for sponsoring that work.

I’ve learned Dorothy and Tanju encountered various issues that prevented them from doing proper mobile tests, and the produced suite tests apps on a regular desktop but with their windows resized to smartphone-like sizes. The goal of my project was to make the test VM provide a smartphone-like screen size and chassis type.

Pixel Density

I’ve first tweaked the VM’s screen to be 360 × 720, but such a small resolution isn’t supported and the tests automatically fail. No big deal, smartphones run on high density devices and we want to test UI scaling, so I decided to switch to 720 × 1440 with 200% scaling… except of course the tests weren’t scaled, why would they be?

To set the scaling factor, we first have to complete the system’s initial setup unscaled, and then once finally logged into GNOME Shell, we discover Settings doesn’t let us change it. This happens because Mutter enables changing the scaling factor only on arbitrarily large-enough resolutions, and 720 × 1440@2 is below the required threshold. At this point, I faced the same issues as Dorothy and Tanju and didn’t go any further, but let’s dig a bit more.

Besides Mutter’s arbitrary limitation, we are facing the need to set the display’s physical size or pixel density so the OS can adapt to it from the very beginning. The best way to do this it is to have an EDID declaring our display’s resolution and physical size, we just need to find the best way to generate it and to use it. We could use a tool like qemu-edid to generate the EDID we want, inject it into the OS, and override the one from the virtual machine, but it would be a messy and dirty workaround.

Our test suite uses QEMU with virtio-vga which offers the following properties:

#define VIRTIO_GPU_BASE_PROPERTIES(_state, _conf)                       \
    DEFINE_PROP_UINT32("max_outputs", _state, _conf.max_outputs, 1),    \
    DEFINE_PROP_BIT("edid", _state, _conf.flags, \
                    VIRTIO_GPU_FLAG_EDID_ENABLED, true), \
    DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1280), \
    DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800)

We already use xres and yres to set the display’s resolution, but there also is the edid property, that openQA toggles on to make QEMU generate an EDID describing the virtual machine’s screen. QEMU has all that’s needed to generate and expose an EDID with the right pixel density, except for a way to let the user override the pixel density that QEMU defaults to 100 DPI.

We could imagine exposing the dpi parameter as a virtio-vga property, making QEMU able to emulate devices with a high density screen, and helping us run mobile tests.

Chassis Type

Then I’ve looked at giving the VM a smartphone’s chassis type. The chassis type is defined in the SMBIOS, let’s read about it in the reference specification:

7.4 System Enclosure or Chassis (Type 3)

The information in this structure (see Table 16) defines attributes of the system’s mechanical enclosure(s). For example, if a system included a separate enclosure for its peripheral devices, two structures would be returned: one for the main system enclosure and the second for the peripheral device enclosure. The additions to this structure in version 2.1 of this specification support the population of the CIM_Chassis class.

Table 16 – System Enclosure or Chassis (Type 3) structure
Offset Name Length Value Description
05h Type BYTE Varies Bit 7 Chassis lock is present if 1. Otherwise, either a lock is not resent or it is unknown if the enclosure has a lock. Bits 6:0 Enumeration value; see below.

7.4.1 System Enclosure or Chassis Types

Table 17 shows the byte values for the System Enclosure or Chassis Types field. NOTE Refer to 6.3 for the CIM properties associated with this enumerated value.

Table 17 – System Enclosure or Chassis Types
Byte Value Meaning
01h Other
0Bh Hand Held

For our QEMU VM to declare being a handheld device, we need to set the SMBIOS structure type 3’s Type field to 0x0B.

According to its documentation, QEMU lets us set some of the SMBIOS fields conveniently via the -smbios parameter. For type 3 we are allowed -smbios type=3[,manufacturer=str][,version=str][,serial=str][,asset=str][,sku=str], so unfortunately it doesn’t let us set the chassis type. QEMU also let’s us set the whole SMBIOS via -smbios file=binary, so we could write the SMBIOS ourselves and feed it to QEMU, but it would be a dirty workaround to an issue that can be fixed. QEMU has all that’s needed to generate an SMBIOS with the right chassis type, except for a way to let the user override the chassis type that QEMU defaults to 0x01 meaning other.

We could imagine adding a chassis=… parameter to -smbios type=3, making QEMU able to fake devices types, and helping us run mobile tests.

Clearing The Way

Adding the dpi and chassis parameters to QEMU’s CLI shouldn’t be too hard, the internals are there, it’s just a matter of exposing these variables. The important part is of course to work with the QEMU project, making sure they are happy with the proposed modifications. If you want to work on that, please let me know! And if you want to contribute to GNOME Mobile’s automated test suite, feel free to do so on the related issue on GNOME’s GitLab instance.

Thanks again to Codethink for sponsoring that work.