⟵ Home

Building an Android ROM with full microG support

· 16 minutes read (≈2894 words)

Since about two years I’m using a LG G6 smartphone. It shipped initially with Android 7 and later got an update to Android 8. Their Android version comes with some LG specific modifications. Nothing too far off from vanilla Android. The UI is fine, I have no trouble in using it. What bothers me are all these pre-installed apps (bloatware). Here is a complete list of all installed apps on my LG G6:

com.hy.system.fontserver com.android.LGSetupWizard com.android.cts.priv.ctsshim com.google.android.youtube com.google.android.ext.services com.lge.sizechangable.weather.platform com.android.providers.telephony com.google.android.googlequicksearchbox com.lge.theme.black com.lge.theme.titan com.lge.theme.white com.android.providers.calendar com.android.providers.media com.google.android.apps.docs.editors.docs com.lge.systemservice com.google.android.onetimeinitializer com.google.android.ext.shared com.android.wallpapercropper com.quicinc.cne.CNEService com.lge.appbox.client com.lge.vrplayer com.lge.lgdmsclient org.simalliance.openmobileapi.service com.android.documentsui com.android.externalstorage com.evernote.promohelper com.lge.android.atservice com.android.htmlviewer com.lge.wfd.spmirroring.source com.lge.app.floating.res com.lge.cloudhub com.android.mms.service com.lge.remote.lgairdrive com.google.android.apps.docs.editors.sheet s com.lge.sui.widget com.google.android.apps.docs.editors.slide s com.android.providers.downloads com.lge.camera com.lge.touchcontrol com.lge.effect com.lge.eltest com.lge.LGSetupView com.lge.homeselector com.lge.ime.solution.text com.lge.springcleaning com.crucialtec.uaf com.lge.gnsstest com.lge.fmradio com.google.android.configupdater com.lge.lifetracker com.lge.smartshare.provider com.crucialsoft.fido.client com.android.defcontainer com.android.providers.downloads.ui com.android.vending com.android.pacprocessor com.lge.myplace.engine com.lge.shutdownmonitor com.android.certinstaller com.dolby.dolbyvisionservice com.android.carrierconfig com.google.android.marvin.talkback com.lge.launcher2.theme.optimus com.lge.ia.task.smartcare com.android.settingsaccessibility com.android.contacts com.qualcomm.wfd.service com.lge.smartshare com.lge.lockscreensettings com.lge.icecontacts com.lge.gallery.vr.wallpaper com.lge.ia.task.incalagent com.android.hotwordenrollment com.google.android.apps.inputmethod.hindi com.android.egg com.android.mms com.android.mtp com.android.nfc com.android.stk com.android.backupconfirm com.instagram.android com.lge.iftttmanager com.lge.exchange com.lge.autosimlockservice com.lge.wapservice com.android.statementservice com.google.android.gm com.google.android.apps.tachyon com.android.calendar com.lge.ia.task.smartsetting com.google.android.instantapps.supervisor com.lge.lgmapui com.lge.lgworld com.google.android.setupwizard com.qualcomm.qcrilmsgtunnel com.android.providers.settings com.android.sharedstoragebackup com.google.android.music com.android.printspooler com.ti.server com.android.incallui com.android.frameworks.telresources com.lge.wfds.service.v3 com.lge.drive.activator com.lge.video.vr.wallpaper com.lge.gnsspostest com.android.inputdevices com.rsupport.rs.activity.lge.allinone com.lge.nextcapture com.lge.gba.android com.lge.eula com.lge.gcuv com.lge.sync com.lge.task com.qti.dpmserviceapp com.lge.themesquare com.google.android.apps.docs com.google.android.apps.maps com.lge.sizechangable.weather.theme.optimu s com.lge.gestureanswering com.android.cellbroadcastreceiver com.google.android.webview com.lge.launcher3 com.lge.musicshare com.android.server.telecom com.google.android.syncadapters.contacts com.android.keychain com.google.android.calculator com.android.chrome com.android.gallery3d com.google.android.packageinstaller com.google.android.gms com.google.android.gsf com.google.android.tts com.lge.gnss.airtest com.lge.signboard.settings com.lge.wifi.p2p com.android.calllogbackup com.lge.bluetoothsetting com.google.android.partnersetup com.google.android.videos com.android.proxyhandler com.lge.updatecenter com.google.android.feedback com.google.android.printservice.recommendation com.google.android.apps.photos com.google.android.syncadapters.calendar com.android.managedprovisioning com.lge.smartsharepush com.lge.themeservice com.lge.filemanager com.facebook.katana com.lge.rcs.sharedsketch com.lge.gallery.collagewallpaper com.android.providers.partnerbookmarks com.google.android.gsf.login com.lge.qhelp.application com.android.wallpaper.livepicker com.android.apps.tag com.lge.easyhome com.lge.hiddenmenu com.lge com.lge.onehandcontroller com.facebook.system com.lge.networksettings com.lge.myplace com.lge.bnr.launcher com.google.android.backuptransport com.evernote com.lge.privacylock com.lge.provider.signboard com.android.bookmarkprovider com.android.settings com.lge.lgfota.permission com.lge.lgaccount com.lge.sizechangable.weather com.lge.globalwfc com.qualcomm.location com.lge.NfcSettings com.android.cts.ctsshim com.qualcomm.qti.tetherservice com.lge.eulaprovider com.lge.bnr com.lge.ime com.lge.mlt com.lge.sos com.lge.appwidget.dualsimstatus com.lge.phonemanagement com.android.vpndialogs com.lge.videoplayer com.qualcomm.location.XT com.lge.lgdrm.permission com.lge.smartdoctor.webview com.lge.wifisettings com.android.phone com.android.shell com.android.wallpaperbackup com.android.providers.blockednumber com.lge.drmservice com.lge.videostudio com.lge.sizechangable.musicwidget.widget com.android.providers.userdictionary com.lge.lteconfig com.lge.faceglance.enrollment com.lge.hifirecorder com.lge.cic.eden.service com.lge.gnsslogcat com.android.location.fused com.android.systemui com.lge.provider.systemui com.android.bluetoothmidiservice com.lge.provider.lockscreensettings com.lge.clock com.lge.email com.facebook.appmanager com.lge.leccp com.lge.music com.lge.qhelp com.lge.remote.setting com.lge.inputdevices com.lge.friendsmanager com.lge.gametuner com.lge.hiddenpersomenu com.crucialsoft.asm com.lge.lginstallservies com.lge.signboard com.android.bluetooth com.qualcomm.timeservice com.qualcomm.atfwd com.android.providers.contacts com.lge.snappage com.lge.servicemenu com.android.captiveportallogin com.lge.ime.solution.handwriting com.lge.theme.highcontrast com.lge.mptcphiddenmenu

Thanks. But no thanks.

Entering the world of custom ROMs

This is way too much bloat for my taste. A lot of useless, proprietary LG apps that, maybe or maybe not, want to phone home – in addition to all the standard Google spyware. On top of that, I’m accusing LG of developing not the most secure software in the world (*wink* *wink*1). Every listed app is a potential attack surface. To be fair: Most of the apps can be uninstalled or deactivated.

Since I’m a privacy and security focused guy, I tried out an alternative Android ROM quite early after I purchased the G6. One of the most obvious choices is LineageOS. Their modifications are relative minimal. They have some unique features, but most of them are unobtrusive. The list of pre-installed apps is, compared to LG’s list, really small. Most of the apps are even open source.

As far as I remember correctly I tested the version 14.1 based on the now deprecated CyanogenMod. Unfortunately, this is the last official release for LG G6 up until now. It’s based on Android 7.1, released somewhere end of 2016. LG itself released an update to Android 8.0 later on, but no official release from Lineage was ever published.

But we’re not finished here: I wanted to get rid of Google too! Using Android without Google sounds like a contradiction, since Android is development by Google. The Android Open Source Project (AOSP) itself is open software. In fact, LineageOS is based on the AOSP project. Nonetheless, more and more essential parts of the OS are now closed source. I want an operation system with no, or at least with as little as possible closed source components. That means, I have to get rid of all Google services including Mail, Geo-Location, Push-Notifications or even the Play Store itself. Just using LineageOS with gapps does not take me closer to this goal.

To the rescue: microG

The microG project tries to re-implement all those proprietary user space apps and libraries. (Almost) all functionality can be archived with microG without using any Google service or closed source component. There’s only one catch: You can’t just use any random Android ROM, neither the original from your vendor nor LineageOS.

To use the full potential of microG, you have to modify some deep rooted system files. The microG team is aware of this problem and has a solution: They provide custom LineageOS builds available with full microG and native F-Droid support.

For most users, this is probably the best solution available. Depending on you actual device, it’s quite easy (read: there are a lot of tutorials) to install custom ROMs. However, if you have for any reason a non officially supported device, you are also out of luck here. In my case, the last LineageOS release available is 14.1 (aka Android Nougat 7.1). Version 16.0 (Android Pie 9.0) is the most recent one at the moment. I could live with an older Android release, if there weren’t all those unfixed security holes.

Building your own ROM

Even though there are no official Lineage releases, there are unofficial ones! These are created and maintained by a loosely coupled community of vastly different users. Some ports are working great, some are buggy and some are just for testing. In my case, the unofficial LineageOS 16.0 ports is quite stable without any major limitations. VoLTE and Wifi calling doesn’t work. Or 5.0 Ghz hotspot. Nothing fundamental. Nothing I really need.

Unfortunately all these ROMs are prepared to be used in combination with Google services, not with microG. But at least we have the source code and can build our own Android ROM.

Step 1: Setup a development environment

Before we can start creating our own custom ROM, we need to have all necessary tools installed. The simplest way I found was using the docker image from the microG team that they use them self to build their version of LineageOS. The source code to build the docker image is available at Github. Alternatively, a prebuilt image is ready to download at Docker Hub.

I used docker-compose to set up a new docker container:

version: '3'
services:
  lineage-build:
    image: lineageos4microg/docker-lineage-cicd
    volumes:
      - "/srv/lineage-build/lineage:/srv/src"
      - "/srv/lineage-build/zips:/srv/zips"
      - "/srv/lineage-build/logs:/srv/logs"
      - "/srv/lineage-build/cache:/srv/ccache"
      - "/srv/lineage-build/keys:/srv/keys"
      - "/srv/lineage-build/manifests:/srv/local_manifests"
    environment:
      - "BRANCH_NAME=lineage-16.0"
      - "DEVICE_LIST=h870"
      - "SIGN_BUILDS=true"
      - "SIGNATURE_SPOOFING=restricted"
      - "INCLUDE_PROPRIETARY=false"
      - "CUSTOM_PACKAGES=GmsCore GsfProxy FakeStore MozillaNlpBackend NominatimNlpBackend com.google.android.maps.jar FDroid FDroidPrivilegedExtension"
      - "ALLOW_MISSING_DEPENDENCIES=true"
      - "WITH_SU=true"

You need to change at least the device name at line 14. You probably need to change some more variables depending on your system configuration and your own taste. More details and examples can be found in their repository.

Step 2: Configuration

The build script needs to know where the sources for your device is located. If your device is officially supported, then you can skip this section, otherwise you need to create a configuration file – a so called manifest file. All manifest files must be saved under /srv/lineage-build/manifests (or whatever you defined in the volume section of your docker-compose file). The name of the manifest file is not important but should end with .xml.

The configuration for my device looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  <project name="LG-G6-dev/android_kernel_lge_msm8996" path="kernel/lge/msm8996" remote="github" revision="caf" />
  <project name="LG-G6-dev/android_device_lge_h870" path="device/lge/h870jd" remote="github" revision="aoscp" />
  <project name="LG-G6-dev/android_device_lge_msm8996-common" path="device/lge/msm8996-common" remote="github" revision="pie" />
  <project name="LG-G6-dev/proprietary_vendor_lge" path="vendor/lge" remote="github" revision="caf" />
  <project name="LG-G6-dev/android_device_lge_g6-common" path="device/lge/g6-common" remote="github" revision="pie" />
</manifest>

The kernel sources, device tree, vendor blobs, etc are located in different github repositories. You will most likely find all necessary information for your device in the xda forums. You can also try to find the right repos with the help of the Github search function. For example, the device tree is most likely called android_device_[vendor]_[device name]. Some repositories contain a file called lineage.dependencies that will help to find further source location like the common tree or vendor blob.

You will most likely also want to include prebuilt packages for microG und F-Droid. You can do this by creating another manifest XML file with the following content:

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
   <project name="lineageos4microg/android_prebuilts_prebuiltapks" path="prebuilts/prebuiltapks" remote="github" revision="master" />
</manifest>

3. Step 3: Compiling

Starting the container will fetch all necessary git repositories and start compiling your Android ROM:

docker-compose up

This will take several hours depending on your hardware. The installable zip file will be located at /srv/lineage-build/zips (if everything works). You can then install the zip file with TWRP. Don’t forget to back up all your data!

Screenshot_20191024-191610_Settings.png Newest Android security patch level. Yeahh!

Errors while building the kernel

At first I had problems building the Linux kernel. Traditionally the Linux kernel must be build with gcc. For some time now the kernel developers tried to get rid of all the gcc specific code. I am not sure what the current state is for the vanilla kernel, but as far as I know gcc is in most cases your only option.

The Android Linux kernel is not vanilla. They added a lot of custom patches. One of the thing they changed, was that the Android kernel can be fully build with CLANG instead of gcc. But at least in my case I had trouble with it and got some obscure error messages while building the kernel. The simplest fix for me was to build the kernel with gcc. To do this, you just have to set the TARGET_KERNEL_CLANG_COMPILE to false in vendor/lineage/build/tasks/kernel.mk.

Unfortunately, this file will be overwritten each time you use the /root/init.sh script that gets called automatically when you start the container. My solution to this problem is to use a file called /root/userscripts/pre-build.sh to overwrite this value each time:

#!/usr/bin/env bash

echo "Disable CLANG kernel build" sed -i '1s/^/TARGET_KERNEL_CLANG_COMPILE = false\n/' /srv/src/LINEAGE_16_0/vendor/lineage/build/tasks/kernel.mk

The provided build script will call this file before the actual build starts. The kernel will now be build with gcc :)

Updating

Normally you would only need to restart the container to update and rebuild everything. Normally. Sometimes, actually quite often, it fails due to problems updating all git repositories. In the end, I updated my docker-compose file to let it run in the background indefinitely:

services:
  lineage-build:
    image: lineageos4microg/docker-lineage-cicd
    stdin_open: true
    tty: true
    entrypoint:
      - /bin/bash
[...]

I can then jump straight into the container with docker exec -ti lineageos_lineage-build_1 bash and run the following command to update all repositories:

cd LINEAGE_16_0
repo sync -c --force-sync

If there is any problem, e.g. file conflicts, I can then fix them manually until the repo sync command works. Afterwards a simple /root/init.sh will start the normal build process.


  1. Not that Vanilla Android from Google is that much better… 


$ whoami

I'm Jens Dieskau, an ordinary software developer & infrastructure operator (don't call it Dev[Sec]Ops) from Germany. I like to tinker with a lot of different open source projects – with focus on Linux in general, security, decentralisation and self hosted solutions.