User:TheKit/Hybris

From postmarketOS

What is libhybris?

libhybris is a compatibility layer, allowing libraries compiled with bionic libc (used in Android) to be loaded by applications built with different libc (originally glibc, musl in postmarketOS case).

How it works?

libhybris includes modified Android linker and provides android_dlsym function which can be used by host libc applications to load bionic libraries. Bionic libc gets loaded into process space alongside host libc, but with many functions hooked or replaced with host libc ones to avoid various memory structs incompatibilities between two libcs.

However, for this to work, there are few Android-side libraries to be patched. This is necessary to avoid thread-local storage (TLS) slots conflicts, as Android has reserved private slots for system libraries such as libEGL which do not require allocation through pthread API and accessed directly through CPU register containting thread pointer, which causes host libc data to be ovewritten.

Halium and mer-hybris already include patches to workaround that, but if you use different Android tree, the following needs to be applied:

Running Android services in LXC container or chroot

This is not strictly required to use libhybris itself, but is generally needed, as Android drivers expect Android init to be running, which provides property_service, does HW-specific initialization via init.$soc.rc script and starts vendor-specific services.

Halium solves that by providing minimal modified Android base which can run inside LXC container and system-side scripts to do that (lxc-android package in pmOS). If your device supports LineageOS 14.1, it might be easiest to port Halium and use resulting system.img with lxc-android.

Otherwise it is also possible to run Android init in chroot with graphical services such as zygote disabled. mer-hybris tree (built for SailfishOS ports) is an example of that and contains modifications needed for libhybris to work.

Utilizing libhybris in different subsystems

Graphics

Android HAL requires device vendors to provide HWComposer API implementation. That API can be utilized via libhybris by Wayland compositors or Xorg to output graphical buffers on screen (as opposed to writing to fbdev directly).

The following projects support it:

Sound

PulseAudio Droid modules allow PulseAudio to use Android HAL via libhybris. While it is possible to use ALSA directly, this approach has benefits of reusing Android mixer configs, which get very tricky on embedded devices such as phones: https://github.com/mer-hybris/pulseaudio-modules-droid.

Cellular

There are two different implementations of RIL plugin for ofono whichs allows it to communicate with Android's RIL daemon for cellular network connectivity (both data and calls).

Camera and media decoding

GStreamer plugin is maintained by SailfishOS - https://github.com/sailfishos/gst-droid. It requires https://github.com/sailfishos/droidmedia to be compiled against device Android tree and minimedia daemon running.

The alternative approach utilized by Ubuntu Touch is to use libcamera_compat_layer and libmedia_compat_layer. They comprised of libraries that need to be compiled against Android (compat folder of libhybris) and libhybris wrappers. Does not work with Android 7 and newer yet.

Useful libhybris tests

  • test_vibrator - basic libhardware test, can be used to check if libhybris and Android root are setup properly, phone should vibrate on launch
  • test_egl_configs - should output available EGL configs before exiting (usually dozens of them), initializes EGL but does not do any output
  • test_hwcomposer - run it with EGL_PLATFORM=hwcomposer test_hwcomposer, phone should render spiral on success
  • test_audio - attempts to load Android audio HAL, not always indicative

test_egl/test_glesv2 are known to be broken as they do not initialize HWComposer API required for EGL window on modern devices.