Android Lollipop 5.0 for the Fairphone 1

Tags: #<Tag:0x00007fefbf956e90>


I have been working for quite some time on Android Lollipop 5.0 (specifically, CyanogenMod 12.0) for the Fairphone 1 and, finally, I am unveiling what I have done.

But do not get too excited yet; this is not a fully functional Android Lollipop 5.0 at all. Hardware accelerated 3D graphics, sensors, basic GPS or Wi-Fi do work, but audio, telephony, Bluetooth, FM radio or camera do not (for a more detailed description see below).

That is a letdown, I know. Another letdown for some of you will be finding out that this Android Lollipop 5.0 version is compatible ONLY with the Fairphone 1 with the original storage layout. Do NOT use it on a Fairphone 1 with the unified storage layout, no matter if it is a Fairphone 1 or a Fairphone 1 (U).

But the worst part is that a fully functional Android Lollipop 5.0 for the Fairphone 1 is not achievable without the source code for the proprietary binary blobs which, obviously, I do not have access to. Therefore, I have no plans to work further on Android 5.0 for the Fairphone 1.


This Android 5.0 version does not add any feature that requires special hardware support and that was not already present in the official Android 4.2 version for the Fairphone 1. Moreover, as I said above, it does not even support all the features supported in that version.

Software-based features are mostly supported. As the Android base is free (as in freedom, not as in free beer) and open-source software (from now on, FOSS) its source code is available for everyone and it can be modified if needed to support a new version of Android on an old device.

However, most features that require special hardware support depend on proprietary binary blobs. That is, precompiled pieces of software for which no source code is available. As there is no source code they have to be used as is; it is not possible to modify them to add new features, fix bugs, adapt to newer Android versions… nothing.

Feature summary

(Please excuse the technical jargon used in some of the feature explanations; although I tried to keep them accessible some of them also include developer-oriented information)
  • Graphics: working. With proprietary binary blobs, graphics are hardware accelerated by the GPU and support OpenGL ES 2.0. Otherwise, graphics are rendered by the CPU with support only for OpenGL ES 1.0 (which shows certain problems in the system GUI).
  • Sensors: working. Requires proprietary binary blobs, but it could be reimplemented in a fully FOSS way (like done in Replicant for other devices).
  • GPS: working. Only basic GPS works; more advanced features like A-GPS or those introduced after Android 4.2 (like geofencing) do not work. Requires proprietary binary blobs.
  • Wi-Fi: working. The software part is fully FOSS, but dependent on proprietary firmware.
  • Wi-Fi Direct: I am not really sure about its status :P I could test it only against another device and it did not work (before Android 5.0 it worked depending on which device provided certain parameters), but I do not really know whether it is a problem in the Android 5.0 version for the Fairphone 1 or in the other device (although, having seen the change that I needed to do in the kernel for the Wi-Fi to work, I suspect that the faulty one is my Android 5.0 version).
  • Power saving: partially working. None of the new power saving features introduced after Android 4.2 that require explicit hardware support work (for example, batching sensor reads or Wi-Fi scans). However, those features that require explicit hardware support and were available already in Android 4.2 still work (for example, disabling CPU cores when the system is not loaded), and newer features that do not require explicit hardware support also work (for example, disabling animations when the battery saver is enabled).
  • Audio: not working. Well, as a matter of fact, I made it partially work just using the proprietary binary blobs. However, as I have said it only worked partially; recording at low bitrates did not work and playing high priority short sounds (like a tap/click sound) did not work (unless there was another sound already playing). Due to this I did not include support for audio in the repository. Another reason was that, in this case, rewriting the audio support in a fully FOSS way seems feasible and not very complex (it would require porting the current audio kernel driver to the ALSA SoC platform and then pairing it in user space with one of the already existing audio HALs for ALSA SoC).
  • Bluetooth: not working. It may be possible to make it work without proprietary binary blobs for the software part thanks to Bluedroid or Bluez, although probably some glue code between those projects and the kernel would have to be written (but I have not checked it). However, just like the software part for the Wi-Fi is fully FOSS but dependant anyway on proprietary firmware, the software part for the Bluetooth, be it FOSS or proprietary, will depend too on proprietary firmware.
  • Telephony: not working. I have not checked if the source code for the proprietary binary blobs is needed to make it work or if it can be made with just the proprietary binary blobs. However, I assume that the proprietary binary blobs are not compatible with a standard system, as they provide support for dual SIM even if in Android 4.2 only a single SIM card was supported, so their source code will be needed to make them work in a standard system.
  • Camera: not working. It seems impossible to make it work without the source code for the proprietary binary blobs.
  • FM radio: not working. It seems impossible to make it work without the source code for the proprietary binary blobs.
  • Hardware accelerated codecs: not working (so most videos do not work with the default Gallery; you may want to use the mighty (and GPL licensed! :) ) VLC instead). It seems impossible to make them work without the source code for the proprietary binary blobs.
  • Hardware composer: not working. It seems impossible to make it work without the source code for the proprietary binary blobs.
  • SELinux: not working. It can be made to work without proprietary source code. It requires some kernel patches that can be got from the official Android kernel and then just configuring it appropriately.
  • Tethering: not working. Support for tethering over USB could probably be added using only FOSS components (at least, the tethering itself; the connection to be shared may require proprietary components anyway, like the Wi-Fi firmware). Support for tethering over Wi-Fi would require at least the use of the proprietary firmware; it should not require proprietary binary blobs for the software, but I have not checked it. And tethering over Bluetooth... well, it would depend on how Bluetooth was implemented, but it looks like at least the proprietary firmware for the chip would be required.
  • Alarm with device powered off: not working. As audio is not available I did not bother making the alarm work. However, it should be possible to make it work without proprietary source code or binary blobs; it should be just a matter of checking in the kernel what happens when an alarm is set in the original Fairphone 1 operating system and replicating it in the Android 5.0 version.
  • Battery stats: not working (how much does each application consume; the current battery level is shown as expected). It requires just a configuration file with the current consumption of several components of the device, but I do not have the equipment to perform the measurements (and I can not extract them from the original Fairphone 1 operating system, as I do not know which license is that data under).
  • Auto-brightness: not working. It requires just a configuration file that associates values provided by the light sensor with values of brightness for the screen.
  • Unique device ID: not working. It requires just patching init (the command that initializes the system) to get the value from a specific file provided by the kernel.
  • Encryption: not tested.
  • GAPPS (Google Applications): not tested. However, F-Droid (the Free and Open Source Android App Repository) works ;)

Known problems

  • When proprietary binary blobs are not used, the graphics system will be slow due to being rendered by the CPU instead of the GPU. However, when the proprietary binary blobs are used, the graphics are not as smooth as they should in Android 5.0, because the proprietary binary blobs used are those from Android 4.2. You may have noticed in Android 4.2 that graphics "stutter" slightly (it is specially noticeable in objects moving at a slow and constant speed across the screen). This is caused by a lack of synchronization between the GPU and the display. In Android 4.4 a new synchronization system was introduced to solve this, but as the proprietary binary blobs come from Android 4.2 they do not provide that new feature.
  • PhotoPhase (a dynamic wallpaper from CyanogenMod) crashes. It may be a problem in PhotoPhase itself, in the proprietary binary blobs or both. Just use a different wallpaper :P
  • As mentioned above, Wi-Fi Direct may not work properly.
  • The only serious bug that I have found was a total freeze of the user interface apparently caused by the proprietary binary blobs of the graphics system. However, the real culprit here could be the way that I run the Android 5.0 version (installed on a disk image on the external SD card through MultiROM) and not the proprietary binary blobs, as sometimes I have suffered read failures from the disk image that caused the operating system to malfunction (and the only way I found to fix them was to just delete the disk image and install the operating system again in a different one; it seems that kind of use was too much for my humble external SD Card). However, I do not know if there were also read failures involved when that freeze happened or not.

Build and install instructions

If, despite all this, you still want to try this Android Lollipop 5.0 version in your Fairphone 1, keep reading to know how to build and install it.

In any case, please note that I am publishing these instructions and the Android Lollipop 5.0 version in the hope that it will be useful, but WITHOUT ANY WARRANTY. I have reviewed the instructions several times, and I think that I have not missed anything, but I could be wrong. In the same way, I have built the Android Lollipop 5.0 version and used it myself without problems, but if there is any bug or forbidden use that I am not aware of (or I have forgotten to mention) that damages your phone, the data in your phone or whatever… I am really sorry! But I am not buying you a new Fairphone :stuck_out_tongue:

How to build

These instructions are a quick reference of the needed steps in a GNU/Linux system. Please refer to the official Android documentation or any of the guides available on the Internet about building Android for further information.

First of all, create a directory to download all the source code and build it. For example, /home/$USER/CyanogenMod/. Now open a terminal in that directory. Except where otherwise noted, all the following commands are expected to be executed in the CyanogenMod directory.

Get repo, which is the command used in Android to manage the repositories with the source code:

curl https://storage.googleapis.com/git-repo-downloads/repo > repo

And make it executable:

chmod a+x repo

Now initialize the CyanogenMod 12.0 repositories.

./repo init -u git://github.com/CyanogenMod/android.git -b cm-12.0

If you have never used git before, that command will fail. You can ignore the failure and continue with the next step (at least, if you want to download the repositories just to build the operating system and you do not intend to develop anything), or you can configure your name and email address. Do not worry, unless you send any change to a public server it will not be used anywhere out of your computer. Set your name and email address as explained in the failure message (that is, executing git config --global user.email "you@example.com" and git config --global user.name “Your Name”) and then run again the same ./repo init command as before.

Create the file /home/$USER/CyanogenMod/.repo/local_manifests/fairphone_fp1.xml and add to it the following contents so repo knows where to get the sources for the Fairphone 1:

<?xml version="1.0" encoding="UTF-8"?>
    <remote name="fairphone" fetch="https://gitlab.com/danxuliu/" />

    <project name="android_device_fairphone_fp1.git" path="device/fairphone/fp1" remote="fairphone" revision="android-5.0" />
    <project name="android_kernel_fairphone_fp1.git" path="kernel/fairphone/fp1" remote="fairphone" revision="mediatek-mt6589-3.4" />

    <!-- This repository provides the support for the proprietary features. If you do not want them just remove the following line. -->
    <project name="android_vendor_fairphone_fp1.git" path="vendor/fairphone/fp1" remote="fairphone" revision="android-5.0" />

And now tell repo to download all the needed repositories. This will take time and you will need around 50 GBs of space in your hard disk:

./repo sync --current-branch

If you want to use the proprietary features you also have to provide the needed proprietary binary blobs to the build system. The helper script extract-files.sh can extract them either from your device through ADB (please refer to the TWRP installation instructions for further information about ADB) or from an uncompressed Fairphone 1 update file. To use it, open a terminal in /home/$USER/CyanogenMod/vendor/fairphone/fp1 and execute ./extract-files.sh to extract them from your device or ./extract-files.sh to extract them from an uncompressed update file.

In any case, the proprietary binary blobs must come from a Fairphone 1 Android 4.2 release. The proprietary binary blobs from the Android 4.4 release have not been tested, so they may work or not.

Now that you have the code (and, optionally, the binary blobs) you can start the build process itself.

First, prepare the build environment.

. build/envsetup.sh

Then, state that you want to build CyanogenMod for the Fairphone 1, user debug variant (the engineer variant, eng, works too; the plain user variant does not work due to its enforcing of SELinux):

lunch cm_fp1-userdebug

Finally, build the OTA package (a zip file that contains the operating system and is installable through the recovery). This will take several minutes or even hours, depending on your computer. It will also require around 25 GBs of additional space in your hard disk. The -j4 parameter tells make how many files to build in parallel; it should be set to the number of cores of your CPU (in this example, a quad-core CPU). However, building certain files is very memory intensive, so, depending on your hardware, your computer may run out of RAM memory if building several of them in parallel; in that case the build will fail, so you will have to use a lower number (or remove the -jX option):

make -j4 otapackage

Well, in the case of the Fairphone 1, you will have to run it again a second time. The first time it will exit shortly after being started with the message The build system was patched. Launch again the build. The Android 5.0 version for the Fairphone 1 needs some changes in the main source code from CyanogenMod, so I developed a system to patch the source code repositories as needed before building (and when that happens, the build must be launched again). It is an ugly hack, but a necessary one :frowning:

How to install

Please note that I have not tested myself replacing the operating system in the Fairphone 1 by this Android 5.0 version (as I always use the MultiROM way; more on that later). It should work without problems but, I repeat, I have not tested it yet.

Remember that this Android Lollipop 5.0 version is ONLY for the Fairphone 1 with the original storage layout. Do NOT install it on a Fairphone 1 with the unified storage layout, no matter if it is a Fairphone 1 or a Fairphone 1 (U).

Have you checked it and your Fairphone 1 uses the original storage layout? Ok. Then just install the zip file generated in /out/target/product/fp1 (the name would be something like cm_fp1-ota-<random letters and numbers>.zip) with the TWRP recovery for the Fairphone 1. Do NOT use the official Fairphone 1 recovery (I have not tested it, so it may work flawlessly or it may brick your phone; I have no idea, but you have been warned :wink: ).

Obviously, installing the zip WILL REMOVE the current operating system installed in your phone, so ensure that you have made all the needed backups. Moreover, after installing the zip you should also wipe your data partition; otherwise, the new operating system could use an incompatible configuration from the current operating system. Again, ensure that you have a backup of your data partition before wiping it or you will not be able to restore the partition when going back to the previous operating system. And, when going back to the previous operating system, as explained in the TWRP article, remember to NEVER install an official Fairphone 1 update through TWRP.

Also note that, although the contents of the system partition are exclusive of each operating system, and the contents of the data partition should be exclusive of each operating system (depending on whether you wiped it or not), the rest of partitions will be shared between the old operating system and the new operating system. That is, if you (or an app) modify something in a system partition like /protect_f and then restore the old operating system that modification will still be there in the restored operating system (which may cause problems in the restored operating system, like losing the IMEI).

However, that should not happen if you do not tinker with the system or use strange (shady?) apps. A more typical scenario would be an app adding some files to the internal SD card partition or you deleting a photo stored there; unless you have a backup of the internal SD card partition its contents will not be magically restored when you restore the previous operating system. Be careful with that!

It is also possible to install a different operating system through MultiROM without overwriting the original operating system (although the issue of shared partitions still applies). Please refer to the article about MultiROM for the Fairphone 1 for further information (but be aware that installing the operating system through MultiROM, although more convenient, is still a delicate matter).

In any case, the first boot into Android 5.0 will take longer than normal, as it has to perform a lot of initializations. Do not worry if your device spends around two minutes in the boot animation (although if it spends five minutes or more, yes, you can start worrying :stuck_out_tongue: ).

Also, you do not have to worry about Android 5.0 replacing your current recovery with its own recovery, as it has none.

And finally, I have not checked whether the Format SD card option in Settings->Backup & reset->Factory data reset resets the data partition, the internal SD card partition, the external SD card or what. If you appreciate your data, do not touch that :stuck_out_tongue:

This article is licensed under a Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license. For the TWRP license please check the source files themselves; those written by me are typically licensed under the GNU General Public License version 3 or later, but in some cases I had to use a different license (for example, in the case of kernel patches they have to be licensed under the GNU General Public License version 2).

:de: Fairphone 1 - Android upgrade
FP1U android 5?
Audio playback support added to Android Lollipop 5.0 for the Fairphone 1
MultiROM for the Fairphone 1
Fairphone 1 maintenance comes to an end
FP1: Macadamia 1.9.9-pre3 Alpha (Android Kitkat)
TWRP recovery for the Fairphone 1
Audio playback support added to Android Lollipop 5.0 for the Fairphone 1
MultiROM for the Fairphone 1
:pencil2: Operating Systems for Fairphones
Why was CM/LOS-for-FP1 development actually stopped?
Android 4 drivers different to Android 5/6/7 drivers?
FP1 Kernel 3.4.5
Subscription model to continue FP1 development

(This should have been part of the original post, but it was over the character limit)

Questions and answers

Why CyanogenMod? Why not AOSP or Omni? What about Replicant?

To get a working Android 5.0 version for the Fairphone 1 I did not start directly with Android 5.0. Instead, I preferred to use an incremental approach. First I developed my own Android 4.2 version for the Fairphone 1 (the same version used in the original Fairphone 1 operating system). Once I got that working I updated it to Android 4.3, then to Android 4.4, and finally to Android 5.0.

Therefore, from the main Android based operating systems available, I had to choose between AOSP or CyanogenMod, as Omni appeared with Android 4.3, and Replicant is jumping directly from 4.2 to 6.0 (plus other issues that I will talk about later). The main reason to use CyanogenMod was the integrated kernel build; in CyanogenMod the kernel is built along with the rest of the operating system, while in AOSP you have to provide a precompiled kernel. The CyanogenMod approach is much better in my opinion, so CyanogenMod was the chosen one.

However, there is nothing that prevents the development of an AOSP or Omni version for the Fairphone 1. In fact, I also got a working version of AOSP 5.0 for the Fairphone 1, although I did not include it in the repository due to the aforementioned requeriment of having to include a precompiled kernel too.

Replicant is a different matter, though. While I would LOVE to get a fully working Replicant version for the Fairphone 1 that is unfortunately “impossible” (at least, without an infinite supply of resources, including time :stuck_out_tongue: ). Like most (all?) smartphones out there at the time of this writing (although there are projects trying to change that; the future looks brighter in this regard :slight_smile: ), the Fairphone 1 requires proprietary binary blobs to get a fully functional system. In fact, the Fairphone 1 currently requires proprietary binary blobs to get working audio and telephony, so even a basic Replicant version is not feasible.

While it seems that it could be possible to free the audio part with relative ease, getting the telephony part working in a full FOSS way would be much much harder. If there are devices that can use the telephony in Replicant is just because the Replicant developers achieved the impressive feat of implementing it from scratch (kudos to them!). Unfortunately, it is designed for Samsung phones, and I would not expect a MediaTek compatible version anytime soon… or ever.

Where does the source code in your repositories come from?

As I said above, I got to Android 5.0 in an incremental way, so both the device and vendor repositories contain a branch for each supported version, that is, android-4.2 (CyanogenMod 10.1), android-4.3 (CyanogenMod 10.2), android-4.4 (CyanogenMod 11.0) and android-5.0 (CyanogenMod 12.0). In branches before android-5.0, the device tree also provides support for TWRP and CWM recoveries (I removed them from the android-5.0 branch as they are not compatible with that version). The kernel repository just contains a single branch, mediatek-mt6589-3.4, valid for all Android and recovery versions.

All the source code included in those repositories, even the source code in the vendor repository, are fully FOSS. Well, the kernel repository may include also proprietary source code leftovers in some special directories, but they are not part of the kernel and they are not used for anything, so I chose to ignore them in the previous statement :stuck_out_tongue:

The source code in the kernel repository is based on the source code of the Fairphone 1 kernel published by Fairphone (that is where those aforementioned proprietary leftovers come from), although modified by me to make it work with CyanogenMod 12.0. It is not up to date with the latest official Android kernel (so it does not provide any new security fix), and it does not provide new hardware support or features; it is just a working version of the original Fairphone 1 kernel for CyanogenMod 12.0 (so what it adds are several bug fixes).

The source code in the device repository is written from scratch by me or based on other FOSS projects.

The source code in the vendor repository is also written from scratch by me or based on other FOSS projects. Ironically, that FOSS source code either depends on proprietary binary blobs (for example, the software part of the Wi-Fi support is fully FOSS, but it depends on proprietary firmware) or is used to provide support for proprietary binary blobs (for example, a GPS proprietary binary blob has to be wrapped by a FOSS component to be used in an updated Android system).

You may be wondering “Did Fairphone not publish the source code for the Android system even if they published it for the kernel? Why?”. Well, the Linux kernel is licensed under the GNU General Public License (GPL) version 2. The GNU GPL is a (strong) copyleft license, which means that anyone distributing a compiled kernel (for example, installed in a phone) must distribute too the source code for that kernel (and the code will still be under the GNU GPL). It is a legal requeriment.

However, for the most part, Android is licensed under the Apache License version 2 and other permissive/non-copyleft licenses, like the BSD. This means that anyone can get the source code for Android, modify it, and distribute a compiled Android system, but she does not have to distribute any source code for that system (well, except for the parts under a copyleft license). In fact, as far as I know, originally even Fairphone had no access to the source code of the Android system (re)distributed by them, as it was directly provided by the manufacturer; they had to negotiate it (hats off for getting it, it had to be a tough one!) to be able to provide updates for the system. However, as you may imagine, even if they have that source code they can not freely distribute it outside the company.

If you do not have access to the source code of the proprietary binary blobs, how did you add support for some of them? Why is it impossible to finish Android 5.0 for the Fairphone 1 without that source code?

Let me start by giving you some context. Android is composed by several layers, one on top of the other. Each layer provides certain functionality to its upper layer and uses the functionality provided by its lower layer.

The topmost layer are the apps; this is the layer that users directly interact with. Below is the Android layer; it provides all the features needed by the apps and it is what makes Android to be Android. But, how do you get a common Android system on thousands of different types of Android devices? Enters the hardware abstraction layer (HAL). As its name suggests, this layer abstracts the hardware below it. It is an interface, a contract that the Android layer can rely on. The Android layer knows that if it has to use certain hardware feature it just needs to send a message to the HAL with a specific format and the hardware will do whatever is expected of it to do, no matter which device and hardware is the Android layer running on.

Between the HAL and the hardware there is still another layer, the Linux kernel. This is the core of the operating system, and it is the layer that makes possible for the software to talk with the hardware. It is an abstraction of the hardware too, but at a much lower level; the HAL layer takes care of translating the Android layer request to the interface provided by a specific kernel driver, but a kernel drivers translates the requests received in the interface that it offers to the appropriate electric signals for the chipset that it controls.

Of course, that was a simplified scheme and in the real world things are not exactly like I have just told (yes, they are way more complex :wink: ), but I hope that you get the idea.

Each Android version provides a set of new or modified features from the previous one. When these features are fully implemented in the Android layer and do not need anything new from the HAL nothing else is needed by a device to make use of them. For example, the Material Design interface. However, the HAL may be extended or modified to support a new feature, in which case the specific HAL for the device and probably the kernel have to be updated for the device to provide that feature. In that case, even the hardware usually needs to explicitly support the feature. For example, the device must have a fingerprint sensor in order to unlock the screen using your fingerprint.

Proprietary binary blobs that provide support for hardware features usually belong to the HAL, although they can be part of the Android layer too (and even of the Linux kernel; although it is licensed under the GNU GPL, which is a strong copyleft license and therefore all its components must be licensed under the GNU GPL too, there are unfortunately some legal and technical tricks to circumvent that requeriment).

The proprietary binary blobs implement parts of the aforementioned contract that the Android layer expects the HAL to comply with. But, as I said before, without the source code of a proprietary binary blob you can not modify it. Do you see where this is going? Yes, if the HAL is modified in a newer Android version the old proprietary binary blobs are no longer compatible. And, therefore, the Android layer can no longer use the hardware features that it provides.

Or, at least, that is what would happen if all the features provided by the HAL were mandatory. Fortunately, they can be optional too. This makes possible to develop a new Android version for an old device even if its hardware or its HAL do not have support for every feature; the newer features are typically (although not always) optional, so the Android layer uses them if available and ignores them if not. In any case, all the mandatory features must be implemented for the device to be declared compatible with that Android version (so technically I should stop calling my version “Android 5.0”… but anyway :stuck_out_tongue: ).

All that is the main reason due to which I was able to add support for some of the proprietary binary blobs. Even if their HAL changed the new features are optional. For example, the sensors HAL added support for batching sensor reads (which reduces power consumption). However, if the sensors HAL does not support that, the Android layer just reads the data as soon as it is generated, instead of a batch of several reads after certain amount of time.

As I said above, in reality things are more complex, and there are other low level issues that have to be handled besides just whether the new features in the HAL are optional or not. For example, if the old proprietary binary blob is also compatible with the newer version of other software elements that it depends on. However, in a lot of cases, as long as the new HAL is backwards compatible and there is source code available for the other elements that the HAL depends on, even if some juggling may be needed, the proprietary binary blob can be made to work in the newer version.

And, at last, we got to the explanation of why it is impossible to finish Android 5.0 for the Fairphone 1 without the source code for the proprietary binary blobs: because the HAL interface that they were built for is not compatible with the HAL from Android 5.0. However, that does not mean that the HAL from Android 5.0 is not compatible with the HAL from Android 4.2. The reason is that the official Android 4.2 version for the Fairphone 1 uses a HAL that is different from the standard Android 4.2 version.

As Android is mainly licensed under the Apache License, the manufacturer got the Android 4.2 HAL, modified it to suit its needs, and then published the proprietary binary blobs based on that non-standard HAL. In the case of the GPS, with patience and stubbornness, I was able to deduce the theoretical interface of their custom HAL and then wrap it to make it compatible with the standard one. However, in other cases like the camera or hardware accelerated codecs, it is unfortunately “impossible” (for those who understand this, it uses smart pointers to C++ template objects; not only that, but their HAL ignores the basic principles of a layered architecture and makes calls to its upper layer…).

Is having the source code for the proprietary binary blobs of a previous version enough to make them work on later versions of Android?

It may be enough, but it is not guaranteed.

One reason for this is that, even if you have the source code, to add support for certain hardware features you may also need to have the technical documentation for the hardware or its firmware (software that runs on that specific hardware instead of on the main CPU).

As a real case example I can point you to the Wi-Fi driver for the Fairphone 1. The program that handles Wi-Fi connections in Android, wpa_supplicant, did not work out of the box with the original Fairphone 1 kernel. After some research I found that the kernel driver (which is GPL licensed and therefore I have access to it) had no implementation for a specific function that wpa_supplicant expects to always be available. However, I could not really implement it, because it had to send a specific message to the Wi-Fi firmware; as I have no documentation for the firmware interface I could not be sure of the exact format of that specific message, and therefore I could not sent it.

In this specific case, however, the kernel can just say “I did what you asked me to do” without doing anything and it works anyway, and in other cases the functionality can be emulated in software, but as you may imagine sometimes there is no way to solve it. If you are curious about all that, check commit 503a9c143c in the kernel repository :wink:

And another reason that may cause having the source code to not be enough to make something work on a later version is, simply, the amount of work needed.

For example, in Android 4.4 the display and the GPU must be synchronized to get smoother graphics. The changes needed in the source code of those elements to add the synchronization may not be too complex. However, the source code of the display driver and the hardware accelerated graphics is massive (well, I do not have access to the full source code that provides hardware accelerated graphics, but I can imagine it :wink: ); although someone not familiar with that source code could be eventually able to make the appropriate changes it would take her a lot of time just to understand it to then be able to make those changes.

However, if it were just a matter of adjusting their modified HAL to a standard HAL then having the source code for the proprietary binary blobs would be (probably) enough.

Besides the proprietary binary blobs, what other problems did you have to overcome?

I lost the count :)

Just to name a few, I had to handle the use of some MediaTek specific headers for the boot images, fix bugs in the original kernel, work around the rather small partition size for the recovery, add support for kexec-hardboot to be used by MultiROM…

For further information please check the commit logs and the source code itself in the repositories, as I always try to document everything properly for future reference.

Why do you not provide prebuilt OTA packages for Android 5.0?

First and foremost, because, probably, I am not even legally allowed to. I have no idea under which license are the proprietary binary blobs in the Fairphone 1, but I would not expect them to be freely distributable. Therefore, I would not be able to include them in the OTA packages. I could provide an OTA package without any proprietary binary blob, but sadly it will not be very useful as you can see in the feature summary above.

And second, because personally I would not install anything provided by some random guy on the Internet, and I expect you to not to do it either :wink: (But, just for the record, even if I am some random guy on the Internet, in my case I am also a good guy and I have no shady intentions :slight_smile: )

Why is there no CyanogenMod 12.0 recovery?

Typically, the recovery uses the same kernel as the normal system, so CyanogenMod builds just one kernel and uses it for both. However, in the case of the Fairphone 1, the normal kernel plus the recovery specific files do not fit inside its recovery partition (its size is only 6 MiB), so the recovery can not be built along with the rest of the operating system. The recovery needs a special kernel configuration to optimize its size, so it must be explicitly built on its own (although the android-4.4 branch must be used for that; as TWRP is a much more powerful recovery than the CyanogenMod 12.0 recovery I have not added support for the later, but it seems that TWRP can not be built on CyanogenMod 12.0 nor Omni 5.0).

“Cannot the special kernel configuration be used also for the normal kernel?”, I hear you ask. Yes, it can. However, optimizing for size usually means losing performance; in a recovery it is not that important, but in a normal system it may provide a worse user experience. Note, however, that it is all just theoretical; I have not made any benchmark or even subjective test for the size optimized kernel and, in this specific case, the impact in performance could be negligible.

What would be needed to make the system work with the unified storage layout?

It should be quite easy, although everything should be triple checked to avoid any horrible surprise ;) It is just a matter of adjusting several configuration and source code files in the kernel and device trees. For the changes needed in the kernel tree see commit 7a4c419a38, in which the original storage layout was set. For the device tree, the changes are needed in the different fstab files, the storage_list.xml overlay file, and the BOARD_USERDATAIMAGE_PARTITION_SIZE parameter in BoardConfig.mk. I think that I have not forgotten anything, but be careful if you try it ;)


Such an impressive work, both on the technical and on the documentation side. Congrats, honestly. People like you is really needed!

Thank you very much.

(I’m a FP2 user, but I just had to post this. It is such a hard task to port mobile OSes, even to devices with released source code as the FP2. I can’t even imagine updating the OS version of an obscure, closed-source device)


@Douwe @jftr: you need to see this! Is it possible to continue the work on this with the source code licenses Fairphone holds?


+1 thanks for doing what you have attempted so far.


Thanks @danxuliu for your great effort. It’s really inspiring to see your work.

@Stefan, we are in contact with @danxuliu (I am especially eyeing his work on TWRP) but please don’t get your hopes up too much. @danxuliu already explains the hurdles he faces and even if we join forces they might be impossible for us to overcome. Additionally, we don’t even have decided whether Fairphone can pour resources into such an endeavor.

Android 6.0 Marshmallow / 7 Nougat for FP2?

Thank you all for your kind words :slight_smile:

In case this helps you to get a rough idea, I invested more than five months of full-time work overall (that is, including CWM, TWRP, Android 5.0 and MultiROM). Yes, it was hard :wink:

Yes, I hope that was clear from what I explained in the article, so please, do not assume that what I have done means that there will be an official update to Android 5.0 for the Fairphone 1. Even with the full source code of a previous version it may be impossible to achieve it.

closed #8

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.

opened #9


(@moderators: Could you please add this post as a comment to my original topic? As I will also need to update the instructions, could you give me write permissions to modify that original topic? Thanks! :slight_smile: )

Do you hear that? It is the sound of a Fairphone 1 running Android Lollipop 5.0 and playing music :slight_smile: And the best part? It is fully FOSS :smiley:

I wrote a new kernel driver for the Fairphone 1 audio system using the ALSA SoC platform and paired it in user space with one of the already existing audio HALs for ALSA SoC (for the time being I just modified the audio HAL for the Samsung Galaxy 3 from CyanogenMod 11.0, but I am still studying other options). It was way harder than I initially expected, as the original MediaTek kernel driver turned out to be just a rather thin wrapper for the hardware while most of the logic is done in their proprietary user space binary blobs (and besides not having access to the source code I obviously had no access either to a hardware datasheet), and the original Linux 3.4 kernel lacked several ALSA SoC features that I had to backport too.

But enough with the details; the important thing is that audio playback works now :slight_smile: I have not uploaded yet the changes to my repository, because I still have to clean up the code, solve some issues and settle on the audio HAL implementation to adapt, but I will try to do it in the next days; I will update the original instructions when everything is ready.

You may have noticed that I have been talking about audio playback, but not audio capture (recording). Well, as you may suspect that is because I have not implemented audio capture yet :stuck_out_tongue: There is nothing special about capture, though; I have not implemented it due to a lack of time (reverse-engineering, even a basic one, is very time consuming :frowning: ), but it would be just a matter of extending the new kernel driver and the audio HAL implementation. However, I do not know when I will be able to do that, as I must focus on other important real life commitments, like finding a job :wink: Anyway, I am probably the only person ever that will use this system, so I am not in a hurry :stuck_out_tongue:


I moved your post and reopened the topic (it was automatically closed after 6 months). I also made your first two posts into wikis so everybody can edit them.


Thank you very much for your efforts! I can assure you that you won’t be the only one using it :wink:


@danxuliu Wow that looks like really awesome work you did. Although I’m not able to test this, as I don’t own a Fairphone 1. Have you ever thought of working for Fairphone officially? Maybe they then could show you the code, so that you would be able to include the official blobs properly, or maybe some modified Version of them.


I second this proposal. Fairphone 1 needs your scholarship and wisdom, @danxuliu.


As soon as it runs on a unified storage with the 1U phone and telephony, GPS, camera are working, I’ll consider using this alpha image.



Glad to read that :slight_smile:

Of course, I would love to! But I am sure that there are other developers much more qualified than me that have applied too, so we’ll see… :wink: Also note that Fairphone’s resources are unfortunately limited, so even if I got hired (which is a lot to suppose :wink: ) I may be assigned to other tasks and not be able to work on this either. Anyway, thanks for your words :slight_smile:

Unfortunately that will be “impossible” without access to the original source code :frowning: (I edited my original response because I wanted it to sound funny, but when re-reading it again it sounded harsh instead, so sorry about that :wink: ).


I will definitely be running the alpha image too. There are so many nicer ways than the current way by Fairphone to do this.

One suggestion is to get a message out to all FP1 & FP1U owners saying something like - “if you want to prolong the life and sustainability of your FP1/U - donate here - all proceeds go to the developer @danxuliu who has special access to our 4.4.4. KitKat source and who might even upgrade it to 5.0.” Completely user funded.


@danxuliu Does anyone have any update on this 5.0?

And any update on the alpha pre3 list of working functions? FP1: Macadamia 1.9.9-pre3 Alpha

I want to install Macademia but can’t find the partion update instructions from here: https://www.fairphone.com/en/tutorials/#/manufacturer/fairphone/device/fairphone/category/software-update/topic/install-storage-upgrade-for-v1-8-7/1

I read that there are 20 000 FP1 & FP1U still in use. Would be nice if community could get something going update wise. :slight_smile: It is getting more and more relevant Blueborne fix for Fairphone 1?


The instructions can be found here:

closed #22

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.