The main difference between traditional desktop oriented Ubuntu and the mobile phone oriented Ubuntu Touch lies in the user interface. Ubuntu Touch is specially tailored to enable smooth, gesture-based control on smartphone screens. This unique user interface is built upon its very own Software Development Kit (SDK) and Application Programming Interface (API), and its practicality and versatility can be seen in the core Dialer, Calendar, and Photo Gallery applications. Unlike its parent, Ubuntu Touch employs a read-only file system. A phone has heightened needs for safety and stability. Although it is not designed for running desktop applications on a routine basis, it is possible to launch some through LXC containers using the Libertine extension. Again, it is not designed to run Android applications but some can run in a Waydroid container. You will experience battery drain and various issues with either approach, so think of those as enthusiast modes., Native applications can be accessed as Click packages through the OpenStore.

A read-only file system

By default, the root directory is set to read-only mode. Certain parts of the file system that require read-write access are linked to /userdata using bind mounts, including directories like /home and /var/log. This restriction on write access serves multiple purposes, foremost among them being the preservation of system stability and the solid availability of a functional operating system. It also acts as a protective barrier against potential harm to essential files caused by third-party apps. Additionally, it simplifies system upgrades and greatly reduces the risk of conflicts. Finally, this approach simplifies the process of conducting a factory reset on the device if needed.

When inspecting mount points, you’ll notice numerous records associated with Halium and other LXC containers. Halium serves as the hardware abstraction layer which enables Ubuntu Touch to function with an Android-based kernel. Essentially, it’s an LXC container that runs Android services and facilitates communication with hardware. A chroot is used to directly access the Android roofs provided by the vendor.

Libertine

Ubuntu Touch is built upon the Ubuntu operating system, commonly used on desktops and servers. However, due to its read-only filesystem, using the  apt install  command is not possible on Ubuntu Touch. To address this limitation, Ubuntu Touch offers Libertine as a convenient solution for running applications in LXC containers, complete with a user interface.

This tool provides a user-friendly interface where you can simply enter the name of the package you want to install. Once the installation is complete, the launcher icon for the newly installed application is seamlessly added alongside other launchers in the main menu of Ubuntu Touch. You can see how this looks in the following video.

The main challenge is that most applications were not designed for small screens or tested on them. Fortunately, Ubuntu Touch has a solution to this through its automatically invoked convergence mode. When you connect a large display via USB-C (or where supported by means of casting), the Lomiri UI automatically switches to a familiar desktop interface. This means that applications can immediately be used in windowed mode, allowing you to resize and move windows, and to perform other actions typically associated with desktop UIs. Remarkably, the phone’s screen simultaneously transforms into a touch-pad.

Waydroid

Ubuntu Touch enables Android applications using Waydroid, which runs these applications in an LXC container, with user interface rendering provided by Mesa, with minimal overhead. Depending on the device, it may use the vendor-provided rootfs or, for devices like the PinePhone, the LineageOS image.

Android applications on Ubuntu Touch can generally be categorized as follows:

  • Work without any issue: Some apps run seamlessly..
  • Fail because they rely on Google Services: Apps relying on Google Play Services, like those using OAuth2 or Google Maps, may encounter issues due to licensing restrictions which block installation on non-Android devices.
  • Cannot be started because they check for bootloader and rootfs consistency: Certain apps, particularly banking applications, check for filesystem consistency and bootloader status, which can pose compatibility challenges.
  • Cannot run since they lack a hardware component: Some apps may have unique hardware requirements or rely on hardware features not fully implemented in Waydroid.

While Waydroid does enable some Android app compatibility, there are a few drawbacks. Beyond the extra CPU usage for managing containers, issues can arise from the interaction of two operating systems, especially during device suspend and wake-up. Non-native apps like WhatsApp can have a greater impact on battery life compared to native apps.

Waydroid is essentially a workaround and needs to be manually installed into the OS. While many things do work, it’s still an experimental feature, and some applications will not function as expected.

Clickable

Native apps on Ubuntu Touch are created using Qt and QML, and they get installed through something called Click packages. These packages are created using a handy tool known as Clickable. It is basically a Python script that bundles together all the necessary tools for app building and development. It includes commands for compiling your app, installing it to your device, running and debugging it, and finally, uploading it to the OpenStore. This process relies on dpkg and Docker containers. Inside these containers, an environment is created with all the needed dependencies in the correct versions. You can easily select your desired target architecture, either x86 or arm64.

To set up the development environment, you start by adding the correct Personal Package Archive (PPA) and running the apt install clickable command. After that, you initialize the environment with the clickable setup command. To create a new project, you use the clickable create command, and when you’re ready to run and debug your project, you simply use clickable desktop. During the first run, a Docker container is automatically downloaded, which handles the compilation and execution of your project.

The resulting file from this process, the Click package, is basically a *.deb package, but has some limitations. Notably, it doesn’t allow external dependencies. Instead, it depends on the UBports framework exclusively. However, if your app must have additional dependencies, you can bundle them into the Click package. These dependencies should be loaded during startup using the LD_LIBRARY_PATH environment variable.

The files from these packages are installed in a directory located at /opt/click.ubuntu.com/hello-world/1.0.0, where “hello-world/1.0.0” represents the app’s name and version. This directory is not included in the PATH environment variable. To start the application, a *.desktop file is used, which launches it from that directory. The script’s path is relative to this directory (for example, ./run.sh). Any user data created by the application is stored in the Home directory. just like with most applications. If you want to inspect the contents of a *.click package, you can do so by renaming it to *.deb and using tools like Midnight Commander.

At first glance, you might think that these applications run within a container, overlays, or similar setup. In fact, the required libraries are used directly from the Ubuntu Touch operating system itself. There’s no need for an additional separation layer because Ubuntu Touch employs a read-only filesystem and AppArmor to manage security between applications.

Ubuntu Touch uses AppArmor categories to control access to all basic APIs, making sure that applications run safely.

Originally published in Czech as Jak funguje Ubuntu na telefonu. You can read it also at ubports.com.

Loading

By Jozef Mlích

Software Developer at GreyCortex, NemoMobile contributor, Micro light aircraft pilot, OpenAlt Conference organizer