Okay, so I'm going to start off with your session.
So Stefan and myself, we're going to be talking about the issues of maintaining an Android
release and how you interact your changes with the upstream AUSP.
So it's called forking, Android considered harmful, and as you can guess the basic idea behind
this is that we should try to avoid forking wherever possible.
So the agenda then, Stefan is going to talk a little bit about the different ways that
you can cope with a changing upstream as a changing AUSP and how you can avoid or how you
typically interact with that and different ways of interacting with that.
And then I'm going to come in and talk about why forking is a bad idea and some ideas
I'd like to discuss both in this session and also offline about what we can do about this.
So quick and true to myself, I think I'm reasonably well known.
I've been doing this stuff for quite a long time.
Main topic is of interest.
The point where software meets hardware, I've always been interested in the interface
with devices and I like to see actual hardware if possible.
I've experienced with Linux and its kernel, Yopto and Android.
I'm very interested in open source and I'm very interested in the idea of communities.
So that's me.
Thank you, hand over to Stefan.
Hi, I'm Steve M. Lankfeld.
I'm living in Germany.
I'm working for Innovax.
We are doing projects and consultancy and I'm doing this and that stuff, Linux and that and what
embedded stuff since 10 years now and yeah, main interest and that it's a system,
things can't be developed and built system, perfect stack and performance analysis set
for myself and the short introduction to the problem is again you.
Sorry, good.
Next slide is slide.
Okay, so yeah, there's P developers, Dalema.
So the first point is the basic one.
So in order to make a product out of an AWS P, you basically need to take a copy of
a USB and then modify it in some way.
So what do we need to do this?
So typically you're adding in board support for whichever hardware platform you're using.
Often you need to put in some custom how support we need to add in services, libraries,
apps and we may also want to change the upstream ASP code, we may want to change the
way the framework works in some ways because we need some different launchary behaviors.
We will of course need to add in some SC policy on all kinds of stuff.
So in order to do anything with AUSP apart from just build an emulator, you need to hike
it around a bit.
So how do you handle that?
And that we go into the section and how we are handling with that.
They are typically so we have to look at two different things.
So one thing as at the one point often have to fork something or at least to patch some
existing code.
So patching framework code for example to fix a bug or back for the patch for a fix or adding
new features in framework but of course this should not be done too much because
and plotting is harder to do versions.
So one thing we always do is fork or patch existing code from the ASP source tree or from
the window tree you get from the SOC window and the better thing is the additions.
So a lot of things we add to the ASP tree for example, how implementations, kind of
drivers, additional apps and other things and both forking and additional patching and
adding code.
I do different tasks that we need to do as ASP developers and in the options I will now
present also done differently.
So we will go to the options that I have seen in the white.
One question?
Okay, no speakers, this mic is only for the so I have to speak louder, you are saying
I should have been louder, okay, okay I tried to speak louder, so now we look at the
four different methods I have seen in the ASP in the community or in projects, how
we deal with that, so we look at the good, the bad and the ugly nothings.
We use at the copy script option I have seen which we are using patches, we are looking
at the local manifest feature from the repo tool and we are looking at the way with copying
and extending the upstream repository repo manifest XML manifest.
That does it for options, we are now going through.
So using a copy script, so we have the upstream for example the upstream ASP source
tree from Google or from a BSP vendor and you are the downstream, you are the downstream
project and in with this option what you are doing is you have kind of in the bad case
you have a separate archive with code, a customer has a separate archive with code or you
have a git repository and in this git repository you have files from the
ASP copied and modified, this is maintained by you, this git repository is maintained
by you and then you are white, a weak me file or you have a weak me file where you specify
the upstream manifest version from Google or from your BSP vendor and the version, so someone
who is working on the code then knows on which version you have based on the copied files
and modified, and then to be very convenient you have a copy script, so you place also a
script into the git repository to then copy the patch files over to the actual ASP source
tree where it was actually built, and how does it check out local like, so you first do
your repo in it from the upstream, except all manifest from Google for example, then you
do a repo sync to download on all the code, then you click git clone the downstream repository
so you code or the code of your customer or your downstream project and then you execute
this copy script, and with this way then you have a patched MSP source tree for your device
or for your customer, and just I will not go much into the pull of cons, of all these
options but I personally don't like this option, but I've seen it, for example, I've seen
it in one upstream git repository here and I've seen it by customers, the problem is it's
very hard to sync the files, the modified files in the ASP source tree and the modified files
in the downstream git repository, it's very hard to track these changes, but I've seen it
and in simple case it works, what also I have seen in the wide is patches on top,
I call it patches on top, how does a downstream project does it, it maintains a git repository
of patches, so not modified files, but patches get patches in the other descriptions,
10 patches, 100 patches, then it also writes a written file to specify the upstream, manifest
an upstream version from Google or the BSP vendor, and also it has a convenient script to
apply the patches on the ASP source tree, how does it look like again, we put in it from
the upstream, it's a manifest, we put sync, you get cloned the downstream project, you
change the directory in the downstream project, and then you execute the convenient script
to apply all the patches, and then the patches are applied to ASP source tree and then you
can build and you are your device enabled, and I've also seen some examples that
in the reload project, in the Pinephone project, and also Chris has a small project, this also
uses patches, so let's before we go to the start option, we look at repo, manifest trick
now that you may know or may not know, it's the removed project trick, this is repo, manifest,
manifest for a small project, you see these lines are adding git repository, so here we are
talking about the addition, but below here we see the, we move project line, that is about
forking, so how we can remove every repository from the upstream and replace it with our own fork,
and this works with the remove project, it's an alt tag, you write down the name or the path
of the repository, then it's been moved, and then since always only adds a new fork of it,
you see that it's a fork because the remote is pointing to cool project, it's not pointing
to the upstream anymore, and cool project is our host on GitHub, so with this, you can do the
option 3, it's the local manifest, the local manifest is a feature by the repo 2, how there's
a downstream project use it, it would mean times a git repository, we'll see local manifest
X and O, so for example, there's some git repository's added, some removed, this X and O
one is in this git repository, again I read me file to specify the versions because you
develop and needs to know that, and then it also adds and forks some repositories of the AOSP,
and plays it on GitHub or somewhere, how does he check out, look like it's again a bit, it's now a
bit shorter, we put in it from the upstream, then we do git clone from the downstream and project,
and the important point is that we clone into the path dot repo slash local manifest, this is
the repo, look in the manifest feature, if X and O files are in this folder, then it's picked up by
repo, and then we do a repo sync and the whole source tree from the upstream source, and now also
from the downstream source, and here also some examples, I've seen from one Raspberry Pi and Android
and also here one from Snap Remote of. Now we go to the force option, but before we do the
force option, another repo trick you might know of it's include, it's a small trick to make it
more easy to maintain a copied or maintain your manifest, the include trick you see here is that
if you have an XML manifest, you can specify the include tag, and if it's included, another text file
is included in this manifest, for example here I copied the upstream manifest from Google versions
13, and then my own additions, my own forks new projects I added in another X and O file, and with this,
you can easily maintain a downstream fork and yeah, and with this we come to the force option
if the option copy and extend the upstream manifest, so now you as a downstream project, you maintain
a own manifest repository, you are not referring to a request, a manifest repository from Google
or the BSP vendor, in that you copy and include the upstream manifest from Google, and you also
again add forks, you add and add and forks some repositories. How to check out it's now where we
easy repo in it from your downstream manifest repository repo sync, and that's it, and you have
Cloncy source code, and examples, the developer does it, project, sell it on does it, and
I cannot spell it, collects OS does it too, and this is the force options, how you maintain your
downstream fork of Android, and why it, and with that I hand over to Chris to talk about
why forking is bad. Okay, so all of the examples are seen really, are in some way rather
forking the upstream project, so yeah, why is this a bad thing, so you may say well it's open source,
we can do whatever we like with it, we can hack this around whatever.
However, forking any project is always about idea, it has a maintenance burden, it's the main problem,
so once you made the fork, you are now responsible for that code for applying security fixes,
bug fixes, whatever else, so you have taken on the responsibility for maintaining this code.
All you can do, you can, instead of backwarding stuff at here into your fork, you can continually
re-base your fork on the upstream version, but that also has some overhead, because when you do the
re-base, you're better have some conflicts and you can have to resolve them and so on.
Next point is something slightly more subtle, I think, when you make a fork and you start
making changes to the code base, those changes tend not to be well separated, so developers often
don't differentiate too much why they're making the changes and they'll be changes to get
commits, but they don't necessarily relate to each other. So you end up with a bit of a mismatch
of stuff, so here's our ESP, here's our fork, we change some stuff, you can look in the
Git logs to find out exactly what we change, but it's not really that obvious.
As a result of all this, we typically end up when you're writing, when you're creating
your own Android device, with a barrier which prevents you migrating to a new version.
So it's quite common to find Android devices running old versions of Android, for example,
Android 9 and running old versions of kernels and, yeah, it's kind of a nightmare.
So to summarize, forking equals technical debt, we would like not to fork if we can avoid it.
So, how do you do this?
Fundamental rule then is don't change a USB code base, including do not change the manifest.
What can you do? Well, you can add stuff, so you can add stuff into the local manifest,
and this is the big thing here really is to enhance patching. So instead of
changing the code in situ, create a series of patches and apply those patches at built-in.
Additional benefit, if you do this in a clever way, you can organize these patches into groups,
which are going to call layers, which can be applied independently of each other, and you have
a much more modular system. My inspiration for this really came from a number of places,
I'm going to document two here, I'm going to mention first of all, Glodroid.
So Glodroid, as we mentioned, is an ASP distro for various boards, including Raspberry Pi's.
And it's interesting if you look at Glodroid 2.0, they change the way that they are interacting
with the upstream ASP, and they're using what they call a mono repository approach,
which is more or less what I just said. This is a little small, and I don't expect you to read
all of it, only one go. The key thing is, no more forking. Okay, so there are ideas,
what I just said in a couple of slides back, instead we will take ASP, we will create a set of patches,
and then we have some build-time tools which will apply those patches to the ASP. This makes it
much more easy to maintain those patches. Also, notice this comment here, it says,
decouple devices or device groups from each other. In other words, we group those patches together
into different functional areas, one for the changes to the ASP code base, some are device specific.
So, that's my first inspiration. My second source of inspiration is from York to Project.
How many people here are familiar with York 2? Okay, about half. Good, right.
So, York 2 is better than Android, yes? I think that was a yes, I definitely heard a yes there.
Okay, so York 2 essentially does the same thing as the ASP build system,
except it does it better in my opinion. Just maybe in a few concepts then, for those of you
are not familiar with it, maybe in York 2 concepts on to ASP concepts. So, in York 2, we have
everything called BitBake, which does the same job as soon. In York 2, we have recipes which are
BB files, bitbake files. They are more or less exactly the same in concept as Android BB files and
make files. And I'm not going to go into this in too much more detail, but York 2 also has classes,
bitbake is written in Python, the classes are basically bits of Python code.
That's where the real logic is implemented in the ASP, the main build logic is implemented in
the build their entries in build make and also in build soon. So, we have this metadata, which
are recipes, classes, and config files. And the key concept I want to borrow from York 2 here
is the idea of a layer. So, we have the called meta layers. So, a meta layer is just a collection
of metadata, recipes, classes and so on. And the key thing here is there are several different types
of layer. So, we have BSP layers. For example, Raspberry Pi would be a good example. We have
distros, distros is a slightly complicated thing which I don't want to go into now, but for example,
AGL, automatic grade Linux is A distro. So, if you want to build an AGL version of York 2,
you just include that layer. And it has what they call software. So, these are typically libraries.
So, meta, Qt would be a good example. Qt is the graphics library. And then when you're building
a product, you just patched together the layers you want. You add in the board support, whichever
board you want. You add in the distro for whatever you want it to do basically. And then you add
in software libraries. Kind of neat. There is an official list of layers, the layer index.
And if you go look there, you'll see there's four or five hundred layers you have to choose from.
So, you can build things together quite neatly. So, why can't we do something similar with Android?
Okay, so this is, okay, I'll misspell that as well. This is a very early stage, but I kind of want
to get to feedback either now or later on. So, how do we apply layers to Android in two minutes?
Essentially, the ASP layer basically is a collection of local manifests, of patches,
and also some metadata explaining what the layer does. And also documenting incompatibilities,
so which version of Android does it work with, that kind of thing.
We do my things up into layers. We can then combine these layers in different ways to add in
what to make whatever we want. So, we can have a board support layer, we can have some house,
we can have build system changes, and so on. And so, we don't want my wonderful diet.
Anybody who see my lectures will know my diagrams are a rubbish, and this is a good example of that.
But the basic idea is that essentially when you import the layers that you want,
so this will be in a directory somewhere on your system. Here I have three layers. I have my BSP,
which is the hardware support. I have a Genog Audio, how and I've got a launcher. And I've
expanded out what you might see under one of these. So, for the audio how, we have some changes
to the hardware directory, a bunch of patches. We have, of course, some SC policy, because you
would need SC policy, a bunch of patches. So, you download the layers you want. You then apply
some magic command to apply the patch, that patches AUSP in a control way, and you build a product.
So, this brings me onto another concept, really, which is a product. So, a product is a collection
of layers, a layers of magic metadata. The product then is a single entity, most likely a file,
possibly in JSON format or something. So, I can then say, go get me the product description from
some URL. It will grab the product description. It will download everything, apply the patch
here and away we go. So, to make this work, we need some tooling, TBD. And just as one final thing,
then the idea is that if I would say, I want to get a product. I want to build, I don't know,
an automotive Android for a Raspberry Pi. Somebody somewhere has written the JSON file, which
explains how to do that. So, I just say, build Android product, point to that JSON file. It will then
read the pilot file, do a repo in it for me to get whichever version of Android, it specifies.
Download the local manifest into the directory, do some checks, do a repo sink in order to bring in
all of the local manifest changes, apply the patches, and then you type M and go away for a long
holiday while it builds it for you. So, that's the basic idea. As I said, this is very much
a work in progress. I would very much value feedback from everybody here. Do you have time for
like maybe one question? Yeah, I'm in charge. So, we have time for one question.
Anybody, I totally overwhelmed. Okay, this is a good reason then to do the wrap up now.
Thank you very much, and let me know what you think.