DEV Community

ying xu
ying xu

Posted on

Technical Analysis: How to Run Android Apps Natively on Linux?

It is well known that the Android system runs on the Linux kernel . However, Android's rich and mature software ecosystem stands in stark contrast to that of Linux ; given that they share the same kernel, why can't Android applications run directly on Linux?

There are currently two main technical solutions for running Android on Linux: virtual machines and containerization . Virtual machines consume significant hardware resources and result in complete isolation—preventing interaction between the two systems—whereas containerization avoids these drawbacks, making it our preferred choice . Specifically, containerization effectively carves out a dedicated space for Android to run within the Linux environment while maintaining a channel for interaction between the two systems .

Therefore, based on this, we decided to create an open-source desktop, OpenFDE, which allows Android applications to run directly on Linux systems .

To provide a better understanding of our open-source project, this article outlines OpenFDE's software architecture and display logic .


1. OpenFDE Overall Software Architecture

┌────────────────────────────────────────────────────────────────────────────────────────┐
│                                   Application Layer                                    │
│   ┌────────────────────────┬────────────────────────┐      ┌────────────┬──────────┐   │
│   │     Android App1       │      Android App2      │      │  X11 APP1  │ X11 APP1 │   │
│   └────────────────────────┴────────────────────────┘      └─────┬──────┴────┬─────┘   │
│                                                                  │           │         │
│                                                            ┌─────▼───────────▼──────┐  │
│                                                            │        XServer         │  │
│                                                            └────────────┬───────────┘  │
├─────────────────────────────────────────────────────────────────────────┼──────────────┤
│                                  API Framework Layer                    │              │
│   ┌────────────────────────┬────────────────────────┐  ┌────────────────▼───────────┐  │
│   │    Activity Manager    │     Window Manager     │  │   X11 Client (libX11, etc) │  │
│   ├────────────────────────┼────────────────────────┤  ├────────────────────────────┤  │
│   │    Content Providers   │      View System       │  │    DIX Driver (wiglamor)   │  │
│   ├────────────────────────┼────────────────────────┤  │            Glamor          │  │
│   │    Resource Manager    │    Location Manager    │  ├────────────────────────────┤  │
│   ├────────────────────────┴────────────────────────┤  │    EGL / GLX / OpenGL/ES   │  │
│   │             Android Runtime (ART)               │  ├────────────────────────────┤  │
│   └─────────────────────────────────────────────────┘  │   User-space Drivers       │  │
├────────────────────────────────────────────────────────┤   (libGL-Mesa-DRI, Mesa3D) │  │
│                                     Native Libs        │  ├────────────────────────────┤  │
│   ┌────────────────────────┬────────────────────────┐  │      LibDRM / GNU LibC     │  │
│   │          SSL           │        Graphics        │  └────────────────────────────┘  │
│   ├────────────────────────┴────────────────────────┤             ▲                    │
│   │   AOSP LibC with Modified Dynamic Libs Loader   │─────────────┘                    │
├─────────────────────────────────────────────────────┴──────────────────────────────────┤
│                           LXC Isolation and Fusion Layer                               │
│   ┌──────────────────┬──────────────────┬──────────────────┬──────────────────────┐    │
│   │ Filesystem Fusion│  Network Fusion  │  IPC Fusion &    │   Clipboard Fusion   │    │
│   │                  │                  │   Acceleration   │                      │    │
│   └──────────────────┴──────────────────┴──────────────────┴──────────────────────┘    │
├────────────────────────────────────────────────────────────────────────────────────────┤
│                           Standard Desktop Device Drivers                              │
├────────────────────────────────────────────────────────────────────────────────────────┤
│                                 Standard Linux Kernel                                  │
└────────────────────────────────────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

The image above illustrates our current overall technical architecture . From the bottom up, the architecture comprises :

  1. Standard Linux Kernel
  2. LXC Isolation and Integration Layer
  3. API Framework Layer
  4. Application Layer
  5. Linux Desktop Graphics Stack

Let us examine each of these components:

  • Application Layer: The FDE application layer primarily encompasses Android applications and Linux X11 applications . While Android applications run natively, Linux X11 applications operate within the Linux system; we integrate their display into the Android environment using a VNC client running within FDE, while simultaneously forwarding input events (such as keyboard/mouse signals and IME inputs) . We are currently developing an Android-based X Server to replace the Linux-based VNC X Server, aiming to achieve superior display performance and enhanced compatibility .

  • API Framework Layer: It provides a set of standard API interfaces that enable applications to communicate and interact with the underlying system; these APIs cover functions such as accessing device drivers, managing file systems, and handling network communications . OpenFDE directly inherits the Android API design framework, ensuring that both adhere to a unified set of APIs for peripherals and power management . This significantly alleviates issues associated with the coexistence of different API generations, as well as the haphazard and chaotic nature of modifications during the usage and development of graphical interfaces .

  • LXC Isolation and Integration Layer: The LXC isolation layer isolates the Linux and Android file systems and API layers while sharing the underlying Linux kernel . The integration layer leverages standard desktop protocols (such as Wayland) and the Linux desktop graphics stack to provide key functions like graphical display, input device management, and window management . Additionally, we are working to package the Linux desktop graphics stack's OpenGL/ES components into dynamic libraries that can be called directly by Android, thereby ensuring compatibility with a wider range of hardware .


2. Display Integration Logic

Having covered the overall software architecture of OpenFDE, let us now discuss how the display component is integrated—a particularly challenging aspect of the entire integration solution .

Standard Linux DRI Display Framework

The logic of the DRI display framework on Linux (currently the most efficient display framework) is that the client directly invokes the GPU for rendering; once rendering is complete, the output is submitted to the compositor, which then performs composition and submits the result for display .

┌──────────────────┐    1. Render Request     ┌──────────────────┐
│ Client/App       ├─────────────────────────>│ GPU              │
└────────┬─────────┘                          └────────┬─────────┘
         │                                             │
         │ 2. Send Composition Request                 │ 3. Fetch Render Result
         ▼                                             ▼    for Composition
┌──────────────────┐                          ┌──────────────────┐
│ Compositor       ├─────────────────────────>│ DPU              │
└──────────────────┘    4. Send Composition   └──────────────────┘
                             Result
Enter fullscreen mode Exit fullscreen mode

Native Android Display Logic

Android's display logic involves the application requesting buffers from SurfaceFlinger; SurfaceFlinger invokes Gralloc to fulfill the request and synchronizes the result for the application's use . The rendering process is executed directly by the application using the GPU, and the final output is handed over to SurfaceFlinger, which invokes HWC (Hardware Composer) to perform composition .

                 ┌──────────────────────────┐
                 │ Application (Self-Render)│<──────────┐
                 └─────┬──────────────┬─────┘           │
                       │              │                 │
  Submit Rendering     │              │ Apply Buffer    │ Return
  Results              │              │                 │
                       ▼              ▼                 │
┌─────────────┐   ┌─────────────────────────┐     ┌─────┴──────────┐
│ Display     │<──┤     surfaceflinger      ├────>│    gralloc     │
└──────▲──────┘   └───────────┬─────────────┘     └────────────────┘
       │                      │ Call
       │                      ▼
       │          ┌─────────────────────────┐
       └──────────┤  hwcomposer (Composition│
                  └─────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

OpenFDE Merged Display Architecture

Running Android on Linux allows these two workflows to be merged :

  1. The initial stages follow the standard Android process .
  2. hwcomposer is modified to act as a Wayland client (thereby losing hardware composition capabilities) .
  3. When SurfaceFlinger requests composition from hwcomposer, the latter returns data indicating that the GPU should handle the entire composition task .
  4. Consequently, SurfaceFlinger invokes the GPU to perform the composition and sends the result to hwcomposer for submission .
  5. Finally, hwcomposer transmits the buffer via the Wayland protocol to the Linux compositor (mutter), which then sends it to the Linux DPU for display .
               ┌──────────────────────────┐
               │    App (Self-rendering)  │<──────────┐
               └─────┬──────────────┬─────┘           │
                     │              │                 │
Submit Rendering     │              │ Request Buffer  │ Allocate
Results              │              │                 │
                     ▼              ▼                 │
┌─────────────┐ Ask  ┌──────────────┴──────┐     ┌─────┴──────────┐
│ hwcomposer  │<────┤    surfaceflinger    ├────>│    gralloc     │
│ (wayland    │     └──────────────▲───────┘     └────────────────┘
│   client)   ├────────────────────┘
└──────┬──────┘ Respond: ALL DONE BY GPU
       │
       │ Transmit Buffer via Wayland
       ▼
┌─────────────┐
│   mutter    │
│(Composition)│
└──────┬──────┘
       │
       ▼
┌─────────────┐
│   Display   │
└─────────────┘
Enter fullscreen mode Exit fullscreen mode

Of course, this approach entails some performance overhead, but it effectively achieves our objective .


3. Summary & What's Next

These are the two core components of how FDE currently operates . Beyond this, we have also worked on integrating Linux applications into Android, upgrading the UI, fine-tuning interactions, and more .

In the next installment, we'll dive into the technical principles behind FDE's Linux application integration .
"""

Top comments (0)