Saturday, October 24, 2015

Understanding how Ubuntu Touch is forked out of AOSP

This post is meant for readers who have familiarity with AOSP building. As I just got my new Nexus 5 x, as a side project, I decided to try to port ubuntu-touch to my old phone: HTC One m7.

First of, Ubuntu touch is built on top of AOSP project. It's using a fork of Android kernel, frameworks, and build system. More precisely, the diagram below explains the architecture:

(note that I didn't draw the diagram, credit goes to Ubuntu's official page: https://developer.ubuntu.com/en/start/ubuntu-for-devices/porting-new-device/)

In the past, Ubuntu Touch project based the Android code they're using of Cyanogen's fork of AOSP (http://cyanogenmod.org), however they recently moved to pure AOSP version. To be precise, by the time of this writing, they're using version 4.4.2.r1. As for my device, since there's a Cyanogen support for it, I think ubuntu-touch can be ported with reasonable effort.

I think using AOSP instead of building the project from scratch is a really smart move. I can imagine that not only it will speed up their development process, but they may also benefit from improvements that Google are periodically making to the code. And the neat thing about AOSP code is that, the Java portion of it is pretty-well isolated from the the build system, making it a perfect fit for Ubuntu Touch that doesn't rely on Java.

Before we begin exploring the changes that Ubuntu Touch made atop of AOSP, I'd like to give a crash intro towards AOSP. First, it is built on top of a modified Linux kernel. Some substantial modifications that are worth to mention are wakelock-support and binder-IPC. The first provides userspace a way to prevent Linux to go to deep-sleep state or LP0. Unlike desktop, when a mobile device is put to sleep (e.g. power button is pressed), we may not want it go to deep-sleep right away. Sometimes we want the sleep to be delayed until a certain task is completed. (e.g. until a data synchronization is completed or until an email is sent). And for binder, it is a lightweight IPC mechanism that is used all over Android. It provides the needed security and flexibility that are expected by a mobile application. For example, when an IPC occurs, the caller identity can be retrieved, which in turns allows an application to see whether the caller has the appropriate permission required for the request. And in terms of flexibility, Google has build a very convenient userspace frameworks on top of its kernel driver implementation. This frameworks allows IPC communication between Java applications, native applications, and even Java-native applications. From my little observation so far, Ubuntu Touch seems to also rely on wakelock and binder.

Now, lets go back to the changes towards AOSP that Ubuntu Touch made. When Android kernel completes its initialization, it calls the very first process, init. This process then does all the userspace initialization, such as creating sysfs nodes and settings proper permissions, and kick-starting different daemons. What's necessary to know here is that init is the one that starts a Java virtual machine that Android heavily uses. init forks itself and runs zygote, which handles all Java-related stuffs. And as Ubuntu Touch does not use Java, a modification was made so zygote never runs. For more details, refer to the code under phablet/system/core. In particular, look for the following commit:

commit 1742098c17be31d968dce45a8eda4552602398c7
Author: Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>
Date:   Fri Jan 10 03:06:09 2014 -0200

    init.rc: adding sensorservice and ubuntuappmanager
    
    Also removing some unused services.
    
    Change-Id: I7881bf436319ed09cbac46450c51710b6cf93c11
    Signed-off-by: Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>

[To be continued...]

1. upstart -> ./ubuntu/upstart-property-watcher/upstart-property-watcher.c:78:#define
http://upstart.ubuntu.com/

2. 

No comments:

Post a Comment