Building and installing for libvirt QEMU virtual machine

Known issues

Please note the following list of yet unresolved known issues when running LineageOS on a libvirt QEMU virtual machine:

Introduction

If you would like to use LineageOS without setting up a physical device, try out Generic System Images (GSIs), or experiment with low-level Android components, this would be a good fit.

These instructions will help you build a LineageOS image that is suitable to run in libvirt QEMU virtual machine.

What you’ll need

Let’s begin!

Build LineageOS

Install the platform-tools

If you haven’t previously installed adb and fastboot, you can download them from Google. Extract it running:

unzip platform-tools-latest-linux.zip -d ~

Now you have to add adb and fastboot to your PATH. Open ~/.profile and add the following:

# add Android SDK platform tools to path
if [ -d "$HOME/platform-tools" ] ; then
    PATH="$HOME/platform-tools:$PATH"
fi

Then, run source ~/.profile to update your environment.

Install the build packages

Several packages are needed to build LineageOS. You can install these using your distribution’s package manager.

To build LineageOS, you’ll need:

For Ubuntu 23.10 (mantic), install libncurses5 from 23.04 (lunar) as follows:

wget http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.4-2_amd64.deb && sudo dpkg -i libtinfo5_6.4-2_amd64.deb && rm -f libtinfo5_6.4-2_amd64.deb
wget http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.4-2_amd64.deb && sudo dpkg -i libncurses5_6.4-2_amd64.deb && rm -f libncurses5_6.4-2_amd64.deb

While for Ubuntu versions older than 23.10 (mantic), simply install:

Additionally, for Ubuntu versions older than 20.04 (focal), install also:

While for Ubuntu versions older than 16.04 (xenial), install:

Java

Different versions of LineageOS require different JDK (Java Development Kit) versions.

* Ubuntu 16.04 and newer do not have OpenJDK 1.7 in the standard package repositories. See the Ask Ubuntu question “How do I install openjdk 7 on Ubuntu 16.04 or higher?”. Note that the suggestion to use PPA openjdk-r is outdated (the PPA has never updated their offering of openjdk-7-jdk, so it lacks security fixes); skip that answer even if it is the most upvoted.

Python

Different versions of LineageOS require different default Python versions.

If your default is python3, but you’re building branch that requires python2, there are various methods to using it, e.g. symlinking it manually or creating a virtualenv for it. We recommend the latter:

Generate the virtualenv once using virtualenv --python=python2 ~/.lineage_venv. Afterwards, activate it in each terminal where you need python2 as default by running ~/.lineage_venv/bin/activate.

The path ~/.lineage_venv can be chosen freely, this is just an example!

Create the directories

You’ll need to set up some directories in your build environment.

To create them:

mkdir -p ~/bin
mkdir -p ~/android/lineage

The ~/bin directory will contain the git-repo tool (commonly named “repo”) and the ~/android/lineage directory will contain the source code of LineageOS.

Install the repo command

Enter the following to download the repo binary and make it executable (runnable):

curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo

Put the ~/bin directory in your path of execution

In recent versions of Ubuntu, ~/bin should already be in your PATH. You can check this by opening ~/.profile with a text editor and verifying the following code exists (add it if it is missing):

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi

Then, run source ~/.profile to update your environment.

Configure git

Given that repo requires you to identify yourself to sync Android, run the following commands to configure your git identity:

git config --global user.email "you@example.com"
git config --global user.name "Your Name"

Due to their size, some repos are configured for lfs or Large File Storage. To make sure your distribution is prepared for this, run:

git lfs install

To avoid duplicated Change-Id: trailers in commit messages, especially when cherry-picking changes, make Change-Id: a known trailer to git:

git config --global trailer.changeid.key "Change-Id"

Turn on caching to speed up build

Make use of ccache if you want to speed up subsequent builds by running:

export USE_CCACHE=1
export CCACHE_EXEC=/usr/bin/ccache

and adding that line to your ~/.bashrc file. Then, specify the maximum amount of disk space you want ccache to use by typing this:

ccache -M 50G

where 50G corresponds to 50GB of cache. This needs to be run once. Anywhere from 25GB-100GB will result in very noticeably increased build speeds (for instance, a typical 1hr build time can be reduced to 20min). If you’re only building for one device, 25GB-50GB is fine. If you plan to build for several devices that do not share the same kernel source, aim for 75GB-100GB. This space will be permanently occupied on your drive, so take this into consideration.

You can also enable the optional ccache compression. While this may involve a slight performance slowdown, it increases the number of files that fit in the cache. To enable it, run:

ccache -o compression=true

Initialize the LineageOS source repository

The following branches are currently supported for building image for libvirt QEMU virtual machine:

Enter the following to initialize the repository:

cd ~/android/lineage
repo init -u https://github.com/LineageOS/android.git -b lineage-22.1 --git-lfs

Download the source code

To start the download of the source code to your computer, type the following:

repo sync

The LineageOS manifests include a sensible default configuration for repo, which we strongly suggest you use (i.e. don’t add any options to sync). For reference, our default values are -j 4 and -c. The -j 4 part implies be four simultaneous threads/connections. If you experience problems syncing, you can lower this to -j 3 or -j 2. On the other hand, -c makes repo to pull in only the current branch instead of all branches that are available on GitHub.

Start the build

Time to start building!

Setup the environment:

source build/envsetup.sh

Virtual A/B partition scheme is used by default. If you would like to use A-only partition scheme instead (which requires less space), run the following command prior to each build:

export AB_OTA_UPDATER=false

Select the build target by running the following command, where <target> is one of the entries in the table below:

breakfast <target>
Target Architecture Type
virtio_arm64 ARM (32-bit + 64-bit) PC
virtio_arm64only ARM (64-bit only) PC
virtio_x86_64 x86 (64-bit only) PC
virtio_x86_64_car x86 (64-bit only) Automotive
virtio_x86_64_tv x86 (64-bit only) Android TV

Now, build the installation image:

m espimage-install

If the build completed without errors, the installation image will appear at out/target/product/<target>/lineage-*-20241220-UNOFFICIAL-<target>.img.

(Optional) Alternatively, you could also build installation image in ISO9660 format (only available for x86_64 targets):

m isoimage-install

If the build completed without errors, the installation image will appear at out/target/product/<target>/lineage-*-20241220-UNOFFICIAL-<target>.iso.

Now, transfer the installation image to the device which you wish to run it on.

Install the virtual machine software

On Debian / Ubuntu, installing the package virt-manager would install the GUI manager, and everything that required for libvirt QEMU virtual machine as well as their dependencies.

Run the following command to install it:

sudo apt install virt-manager

Additionally, install the following packages according to your build’s architecture:

Android Architecture Packages to install
ARM (32-bit + 64-bit) qemu-system-arm qemu-efi-aarch64
ARM (64-bit only) qemu-system-arm qemu-efi-aarch64
x86 (64-bit only) qemu-system-x86 ovmf

Create and configure the virtual machine using virt-manager

Launch virt-manager, by opening “Virtual Machine Manager” from the Application menu, or type it on Terminal.

Virtual machine creation and common configurations

Firstly, click Edit > Preferences > General > Enable XML editing.

Now, on the menu bar, select File > New Virtual Machine. A new window named “New VM” will pop up.

Step 1

Select Manual install, expand Architecture options, and select the correct architecture for the built image, as described below:

Android Architecture QEMU Architecture
ARM (32-bit + 64-bit) aarch64
ARM (64-bit only) aarch64
x86 (64-bit only) x86_64

After selecting the correct architecture, click Forward.

Step 2

Search and select Generic Linux 2022 on Select the operation system you are installing field. Click Forward.

Step 3

Specify the number of CPU cores and the size of memory that you’re willing to allocate to the virtual machine. Minimal RAM requirement is 2048 MiB. After populating these fields, click Forward.

Step 4

Untoggle Enable storage for this virtual machine, as we will setup storage for this virtual machine later. After doing this, click Forward.

Step 5

Specify the name that you would like to assign to the virtual machine, and select the network which you wish to connect to in Network selection menu, click Forward.

Select Chipset or Machine and Firmware

The virtual machine configuration window will pop up.

On theOverview tab, select Chipset or Machine and Firmware type according to the architecture, as described below:

Android Architecture Chipset / Machine Firmware
ARM (32-bit + 64-bit) virt (required) Custom: /usr/share/AAVMF/AAVMF_CODE.no-secboot.fd
ARM (64-bit only) virt (required) Custom: /usr/share/AAVMF/AAVMF_CODE.no-secboot.fd
x86 (64-bit only) Q35 (recommended) UEFI x86_64: /usr/share/OVMF/OVMF_CODE_4M.fd

Click Apply.

On Memory tab, toggle Enable shared memory, click Apply.

Create virtual disks

  1. Click Add Hardware on the bottom left corner, new window Add New Virtual Hardware will appear.
  2. Select Storage, select Disk device on Device type menu, and select VirtIO on Bus type menu.
  3. Fill in the disk size.
  4. Click Finish.
  5. Repeat the above steps, to add disk for storing userdata. Minimum size of 2 GiB is recommended.

Attach the installation image

  1. Click Add Hardware on the bottom left corner, new window Add New Virtual Hardware will appear.
  2. Select Storage.
  3. If the installation image is in ISO9660 format, select CDROM device on Device type menu, and select SATA on Bus type menu; Otherwise, select Disk device on Device type menu, and select USB on Bus type menu.
  4. Expand Advanced, toggle Readonly.
  5. Select Select or create custom storage, select the installation image.
  6. Click Finish.
  7. On Boot Options tab, toggle SATA CDROM 1 or USB Disk 1, click Apply.

Configure virtual machine input

Tablet or Mouse

If the device has a touchscreen and you would like to interact with the virtual machine using a touchscreen, or if you are controlling from remote desktop, you must use tablet input device for the virtual machine.

Otherwise, use mouse input device.

Keyboard

Keyboard is always needed. Ensure there is a keyboard included in virtual machine hardware.

Configure virtual machine graphics

Video

  1. If Video tab is missing, add it using the Add Hardware button on the bottom left corner.
  2. On Video tab, select Virtio on Model menu, click Apply.
  3. If the device and the remote desktop application supports 3D accelerated graphics, Toggle 3D acceleration, click Apply.
  4. (Optional) To specify custom display resolution, first enable Edit XML switch to the XML tab, insert <resolution x="<Width>" y="<Height>"/>, like this:
     <video>
     <model type="virtio" heads="1" primary="yes">
         <acceleration accel3d="yes"/>
         <resolution x="1920" y="900"/>
     </model>
     <alias name="video0"/>
     <address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0"/>
     </video>
    

Display

  1. If Display tab is missing, add it using the Add Hardware button on the bottom left corner.
  2. Open Display tab.
  3. Select None on Listen type menu.
  4. If 3D acceleration is enabled on Video tab, toggle OpenGL, and select an active host video card on the menu below of OpenGL toggle.
  5. Click Apply.

Configure virtual machine sound

Sound card model AC97 (which is the default) is recommended. Other models might work too but may have issues.

Create the new virtual machine

Click Begin Installation in the top left corner, the installation process will proceed, and then the virtual machine will start for the first time.

Install LineageOS to the virtual machine

The virtual machine should boot into the boot manager menu of the installation image.

  1. Select the first option called something akin to Install LineageOS using arrow keys, and then press Enter.
  2. The virtual machine should enter LineageOS Recovery. You could select an option using arrow keys and enter it by pressing Enter.
  3. Select Factory reset > Format data/factory reset > Format data.
  4. Select Apply update > Choose INSTALL > Select lineage-*-20241220-UNOFFICIAL-<target>.zip.

Congratulations! You now have installed LineageOS in the virtual machine.

You can now select Reboot system now to boot into LineageOS.

Run LineageOS inside the virtual machine

The virtual machine should enter LineageOS boot menu.

If the virtual machine is configured with 3D acceleration enabled, boot LineageOS by selecting the first option.

Otherwise, select Advanced options > LineageOS * (Kernel version *) (Swiftshader graphics).

Run Generic System Images inside the virtual machine

Here we will utilize GSIs from the Android Open Source Project website as example. There are three ways to run it:

Dynamic System Updates

  1. When booted into Launcher, open Settings app.
  2. Enable Developer options, go back to homepage, navigate to System > Developer options.
  3. Open DSU Loader, select the DSU package that you wish to install, click Agree.
  4. Once the installation finishes, you could reboot to the GSI by clicking Restart on Dynamic System Updates notification.

Specify GSI image as the third VirtIO disk

  1. Download a GSI image archive (equal or higher Android version with matching architecture) from Generic System Image releases.
  2. Extract system.img from the downloaded archive.
  3. Add system.img as the third VirtIO disk.
  4. Boot the virtual machine into recovery mode, perform factory reset.
  5. Reboot to boot menu, select Advanced options > Boot GSI from /dev/block/vdc with LineageOS * (Kernel version *).

Flash GSI image to system logical partition

  1. Download a GSI image archive (equal or higher Android version with matching architecture) from Generic System Image releases.
  2. Extract system.img from the downloaded archive.
  3. Boot the virtual machine into recovery mode, and perform a factory reset.
  4. Enter fastbootd mode by selecting Advanced > Enter fastboot.
  5. Delete unneeded logical partitions, and flash the GSI image, using fastboot:
     fastboot -s tcp:<IPv4 address that shown on menu header> delete-logical-partition product
     fastboot -s tcp:<IPv4 address that shown on menu header> delete-logical-partition product_a
     fastboot -s tcp:<IPv4 address that shown on menu header> delete-logical-partition product_b
     fastboot -s tcp:<IPv4 address that shown on menu header> delete-logical-partition system_ext
     fastboot -s tcp:<IPv4 address that shown on menu header> delete-logical-partition system_ext_a
     fastboot -s tcp:<IPv4 address that shown on menu header> delete-logical-partition system_ext_b
     fastboot -s tcp:<IPv4 address that shown on menu header> flash system <path to GSI system.img>
    
  6. Reboot to boot menu, proceed with the first option.