Skip to content
agentsco-labPublic

About

item: a shell for the Surface Duo on Droidian - a Wayland compositor of its own in Rust, drawing straight into hwcomposer: two panels, the hinge, the pen, CV ID. An experiment until 1.0.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

485 Commits

Folders and files

Repository files navigation

item

item is a shell for a phone with two screens and a hinge between them, made on the Microsoft Surface Duo 1 running Droidian. It is a Wayland compositor of its own, item-compositor, that draws straight into the phone's hwcomposer with the whole shell - the dock, the shades, the lock screen, the screens at the edges - drawn inside it, in the same GPU pass as the windows. It goes on top of the port, agentsco-lab/surfaceduo-droidian, and takes phosh's place; phosh stays installed as the way back.

Until 1.0, item is an experiment. It is used on one phone, daily, but nothing here is promised to work on yours: a release can break the lock screen, the modem's sleep or the way back to phosh. Keep the port's backups, install with a computer by the phone on the USB cable, and know sudo item-switch phosh. What is done so far is the groundwork - the compositor, its frame path, the gestures and the phone's sleep. Every app and every menu you see will be reworked; they are there to make the phone usable while that groundwork settles.

What it looks like

A minute of it (filmed with 0.2.1, the book only), both panels at 60 fps with the gap between them, filmed from the compositor's own frames: the first setup (the PIN, a finger), the tour, the shade, the system screen, the pen's sheet.

item-0.2.1-first-setup.mp4

Both panels as one picture, taken with itemgrid screenshot (2700x1800, the hinge's strip left out) or as frames of the film (1392x900, the gap black). The wallpaper is Aurora, drawn by the compositor itself.

the desktop a window on each panel
The desktop: the dock in two halves at the panels' outer edges, under the thumbs, and the clock on the free panel. A window on each panel, each at its panel's full height: Clocks on the left, item Settings on the right.
the lock screen the first setup: a finger
The lock screen over the darkened wallpaper. A known face or finger unlocks it as the phone is opened. The first setup, its finger step: the reader's mark under the power key fills as the finger is read.
the system screen the pen's sheet
The system screen, brought in from the left panel's outer edge: the battery, the next alarm and event, the connections, the storage. The pen's sheet from the right panel's outer edge: strokes with the pen's pressure, four inks, undo and redo.

What it does

  • The dock in two halves, under the thumbs. Its pieces are drops of water: they follow a finger, slosh along as the phone folds like a book, cross the hinge to the free panel and join. An app launched from it opens on the panel it was launched from; in the book a window is put away with a swipe up from the panel's bottom edge and called back with a tap. The dock's apps are kept warm: launched after boot and put away before a frame shows them, so a tap brings a window that exists.
  • Windows by panel. In the book a window takes its whole panel, or both when carried across the hinge; turned, a window takes the screen's panel and is put away with a swipe up on its cover. There is no status bar.
  • The keyboard, item's own: English and Russian, signs, and a "vibe" layer for the terminal (esc, tab, ctrl, the arrows, y/n) on which Claude Code is driven with a thumb; a microphone key that types what is said, through OpenRouter with a key of the owner's. The port's stevia stays as a choice.
  • The turn. A button at the end of the dock's right half turns the frame through blur: the right panel becomes the deck - black, the keyboard split for two thumbs, the open windows as a row of covers above it, the pen's sheet and the system screen a swipe to either side - and the left the screen; tapped again, the book. Held, the button turns green and the turn is the sensors': item then reads the hinge, gravity and the gyroscope and turns as the phone is stood up; held again, the button's (Settings' Turn page is the same switch). Locked while stood up, the lock screen is still the book's.
  • Chromium is the browser, resident without a window and asked for one from the dock. The Agent entry is Claude Code in a terminal, warm in tmux, with the keyboard's vibe layer under it; item-agents and item-sync carry sessions and folders between the computer and the phone.
  • A shade per panel, glass over the screen: a status line, brightness, volume, quick settings and the player on the left; the open windows and the notifications on the right. The system screen left of the left panel (the battery with its 24 h graph, the calendar's next event, the device) and the pen's sheet right of the right one, brought in from the outer edge; the pen draws with its pressure, the other end erases.
  • The lock screen: the PIN pad's keys as drops, the fingerprint mark at the reader under the power key. CV ID: a known face unlocks the phone as it is opened - the camera is started at the lid itself, ahead of the panels lighting. The faces enrolled stay on the phone, in /var/lib/item-face, root's alone; the camera is open only while the lock screen is lit.
  • The first setup after a clean install: a welcome, Wi-Fi (the networks in reach, a tap joins one; installed with item/grid the phone is already on the computer's network), whether item may go online by itself, a new PIN (the face taken as it is typed, for CV ID), a finger, then a tour.
  • The phone's sleep is item's: the lid darkens and lights the screen, asleep again 3 s after a wake that lit nothing, woken for alarms, an alarm or a call keeps the screen lit.
  • item Settings: one window across both panels, the sections on the left, one page on the right: Keyboard, Voice, Online, Battery, Date & time, About.

Measured (2026-10-01, item 0.2 against item 0.1 on phosh)

The same Duo 1, timed below both compositors with a uprobe on libhybris' hwc2_compat_display_present - the call both make to hand hwcomposer a frame (compositor/log/2026-10-01-step-21-ab.md and the two after it, in the history at item-v0.2.1). 0.3.1's are in its release notes (the agent's hook 147 -> 4 ms a command; item-sync no longer a busy core on the computer; with the port 0.22.1 the sound ~40 s sooner in a boot). 0.3.0's own numbers are in its release notes: the compositor 712 -> 365 MB resident after the fonts and pictures were tamed, Chromium 0.56 s to its window from the dock, one missed frame a second typing on the deck.

item 0.1 on phosh item-compositor
a tap, from the touch to the present with the app's new frame 17.6 ms (p90 24.4) 6.2 ms (p90 7.9)
the shade pulled back up 6 gaps over 25 ms each time, up to 54 ms 0-1, up to 29 ms
the app grid going down a 235-243 ms freeze each time up to 34 ms
an animating app, its commit to the screen not measurable (phoc reports no presentation) one vsync, 15.8 ms
the shell at rest: memory (PSS) 461 MB (phoc, phosh, dock, system screen, pen) 173 MB
the shell at rest: CPU 3.5 % of a core 2.6 %

Against the Lindroid chain (a virtual DRM device handing frames to hwcomposer), the other way to run a compositor on this kernel: no CPU copy of each frame (the chain spends 9-13 ms and 0.76 W on it at 60 fps), and 60 fps with both panels animating where the chain holds 30 (docs/COMPOSITOR.md).

Other numbers: a frame of the shell renders in 1-1.5 ms; the shade follows the finger 22-26 ms behind it where the same shade through GTK took about 39; CV ID takes about 135 ms a frame on the Duo; a phone shut, Wi-Fi radio on and mobile data off, lost about 1.3 % an hour (2026-10-09, the port 0.21.4, item 0.2.1), and 1.14 % with Wi-Fi off on 0.3.0 (2026-10-23).

How it is made

Rust throughout. The compositor is on smithay (calloop, its GLES renderer) with EGL on the Android platform - hwcomposer's window, no GBM - and hands frames to hwcomposer through libhybris' hwc2 API, with its vsync and fences; touch comes from libinput. Text is rendered with fontdue into textures; D-Bus with zbus (logind, UPower, NetworkManager, the notification server, polkit's agent, gnome-keyring's prompter); the PIN through PAM; the session by gnome-session. CV ID runs YuNet, SFace and MiniFASNetV2 as ONNX models with tract, the camera through GStreamer's droidcamsrc, as a service of its own (item-face). item Settings is GTK4 and libadwaita. The keyboard is the compositor's own (the port's stevia stays as a choice); the hinge is read in-process from sensorfw's sockets, gravity and the gyroscope too while the turn is the sensors'; the browser is Debian's Chromium on Wayland. All of it ships as one Debian package built on the computer for aarch64 (compositor/tools/package-deb.sh).

How the compositor came to be, step by step with its measurements: docs/COMPOSITOR.md.

What it needs, and what it changes

A Surface Duo 1 on Droidian 102 with the port 0.22.0 or later (0.22.1 brings the sound ~40 s sooner in a boot). item disables phosh.service and runs item.service and item-face.service in its place (item-fallback.service starts phosh if item does not come up); it sets the kernel's alarm before sleeping, holds a wakelock while the screen is lit, and keeps its state in ~/.config/item (dock.json, env, warm and what Settings writes: keyboard, keyboard-langs, keyboard-auto, haptic, voice, online). The faces enrolled are in /var/lib/item-face, root's alone, and never leave the phone. Nothing of Droidian's is removed; the port's posture, dock and brightness autostarts are kept out of item's session, mtp-server is masked, and Android's Wi-Fi diagnostics daemon is stopped after boot (item-quiet.service). Three user units come with it: item-warm (Chromium's files read into the page cache after boot; ~/.config/item/warm names more), item-chromium (Chromium resident without a window) and item-agent-home (the agent's tmux session, when Claude Code is installed). They are on by the package's own links, so systemctl --user mask is the way to turn one off; an upgrade's new units and masks take effect at the next boot.

Nothing leaves the phone by itself. item has no telemetry and no account. The one network use of its own, the system screen's weather (met.no, the city chosen in GNOME Weather) and the port's latest release (GitHub), is behind item Settings' Online switch, off by default. The keyboard's voice goes to OpenRouter only with a key the owner put in the phone's keyring (item-secret set openrouter); keys live in gnome-keyring by name and are never written to a file or a log. The screen's mirror for item/grid is a socket in the user's runtime directory and stops while the phone is locked. ~/.config/item/env is sourced by the session for the owner's variables: it is the owner's file, treat it as such.

Installing

With item/grid, the way meant for it. item/grid is the desktop program (Linux) that looks after a connected Duo: it backs the phone up first, puts a ready-made system image on it - Droidian 102, the port and item - RAM-boots the port's kernel on a phone coming from stock Android and writes it to the slots only once it booted there, and afterwards keeps item updated, reads its logs and takes it back to stock Android if you want. Its window shows the phone as it is held and one button for what to do now. It is the computer by the phone that an experiment like this needs. The image it puts on is in the releases too (item-duo1-…: the image, the kernel, item/grid's own recovery, a manifest with the checksums), for item/grid's ~/.local/share/itemgrid/releases/ or for doing it by hand. A phone installed this way comes up with the right time, on the computer's Wi-Fi and in its time zone.

By hand, over a port 0.22.0 or later on Droidian 102:

sudo apt install ./item_0.3.1_arm64.deb
sudo item-switch item

The first start runs the setup. Back to Droidian's phosh, now and for the boots after:

sudo item-switch phosh

item-switch status says which shell the phone starts. Under item, iio-sensor-proxy (phosh's rotation and light sensor) is masked - item reads sensorfw itself, and the proxy once hung sensorfw for everyone after a resume; item-switch phosh brings it back.

Where it stands

  • Every app and menu is provisional: item Settings' pages, the shades' contents, the system screen and the pen's sheet will be reworked once the groundwork is done. Six of Settings' pages (Wi-Fi, Bluetooth, the mobile network, Display, Sound, Lock) are not made yet and say so; Wi-Fi, Bluetooth and mobile data are switched from the left shade, a network's password is asked by the shell.
  • Nineteen wallpapers come in /usr/share/item/walls, photographs from Unsplash with their credits beside them (NAME.txt, "Photo by ..."); the picker, opened by a finger held on the desk, takes one's own pictures from ~/.local/share/item/walls too. The desktop before one is chosen is Aurora, drawn by the compositor.
  • With an Unsplash key of your own in the keyring (unsplash: item/grid's Keys, or item-secret set unsplash), the wallpaper picker has Shuffle: twelve dark photos at a time, searched among dark themes and kept only if their own pixels are dark; a tap keeps one in your set with its credit. Without a key there is no Shuffle, and nothing is asked of the network.
  • Every gradient item draws is dithered - Aurora, the glass, the accent's glow, the dock's drops - so dark gradients on the OLED panels do not fall into bands.
  • Before the setup has run, and with a picture that cannot be read, the screen is black.
  • Tried on one phone. Each step was measured and tried by hand; there is no test suite beyond that.

What is in this repository

compositor/ item-compositor, its session, item-face (CV ID), pen-split, the package build (tools/package-deb.sh), the steps and measurements in compositor/log/
apps/settings/ item Settings (Rust, GTK4 and libadwaita), in the package
docs/ COMPOSITOR.md, SETTINGS.md, SHELL.md (item-shell 0.1 on phosh)
docs/img/item-shell-0.1/, SHELL.md what is left here of item-shell 0.1, the shell as patches on the port's phoc and phosh (released as item-shell 0.1.0, 2026-09-29): its screenshots and its write-up. The code is in the branch and tag item-shell-0.1, superseded by the compositor

License

See LICENSE.

About

item: a shell for the Surface Duo on Droidian - a Wayland compositor of its own in Rust, drawing straight into hwcomposer: two panels, the hinge, the pen, CV ID. An experiment until 1.0.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages