From bae6bfef3f2373e5945049cbbff775b8815636fc Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Wed, 22 Feb 2017 08:09:48 +0100 Subject: [PATCH] Extend documentation with various additional details --- README.md | 207 +++++++++++++++++++++++++++++------------- docs/architecture.png | Bin 0 -> 29330 bytes docs/build-android.md | 110 ++++++++++++++++++++++ docs/runtime-setup.md | 35 +++++++ 4 files changed, 291 insertions(+), 61 deletions(-) create mode 100644 docs/architecture.png create mode 100644 docs/build-android.md create mode 100644 docs/runtime-setup.md diff --git a/README.md b/README.md index 7aee100..f5bc58f 100644 --- a/README.md +++ b/README.md @@ -1,80 +1,139 @@ # Anbox Anbox is container based approach to boot a full Android system on a -regular Linux system like Ubuntu. +regular GNU Linux system like Ubuntu. ## Overview Anbox uses Linux namespaces (user, pid, uts, net, mount, ipc) to run a full Android system in a container and provide Android applications on -any platform. +any GNU Linux based platform. -Android inside the container has no direct access to any hardware. All -hardware access is going through the anbox daemon. We're reusing what -Android has implemented for the Qemu based emulator. The Android system -inside the container uses different pipes to communicate with the host -system and sends all hardware access commands through these. OpenGL -rendering is provided through this. +The Android inside the container has no direct access to any hardware. +All hardware access is going through the anbox daemon on the host. We're +reusing what Android implemented within the QEMU based emulator for Open +GL ES accelerated rendering. The Android system inside the container uses +different pipes to communicate with the host system and sends all hardware +access commands through these. For more details have a look at the following documentation pages: - * Android Hardware OpenGLES emulation design overview + * Android Hardware OpenGL ES emulation design overview (https://goo.gl/O2Yi6x) - * Android Qemu fast pipes (https://goo.gl/jl4GeS) + * Android QEMU fast pipes (https://goo.gl/jl4GeS) * The Android "qemud" multiplexing daemon (https://goo.gl/DeYa5J) - * Android Qemud services (https://goo.gl/W8Lx6t) + * Android qemud services (https://goo.gl/W8Lx6t) + +Anbox is currently suited for the desktop use case but can be used on +mobile operating systems like Ubuntu Touch, Sailfish OS or Lune OS too. +However as the mapping of Android applications is currently desktop specific +this needs additional work to supported stacked window user interfaces too. + +The Android runtime environment ships with a minimal customized Android system +image based on the [Android Open Source Project](https://source.android.com/). +The used image is currently based on Android 7.1.1 ## Installation -As first step you need to install additional kernel drivers for the -Android binder and ashmem subsystems. Those drivers are packaged as -a DKMS package for Ubuntu 16.04 already. You can install them from -a ppa with the following commands: +The installation process currently consists of a few steps which will +add additional components to your host system. These include + + * Out-of-tree kernel modules for binder and ashmem as no distribution kernel + ships both enabled. + * A udev rule to set correct permissions for /dev/binder and /dev/ashmem + * A upstart job which starts the Anbox session manager as part of + a user session. + +To make this process as easy as possible we have bundled the necessary +steps in a snap (see https://snapcraft.io) called "anbox-installer". The +installer will perform all necessary steps. You can install it on a system +providing support for snaps by running ``` - $ sudo apt install software-properties-common - $ sudo add-apt-repository ppa:morphis/anbox-support - $ sudo apt update - $ sudo apt install anbox-modules-dkms +$ snap install --classic anbox-installer ``` -Anbox is available as a snap in the public Ubuntu Store. Currently it -is only available in the edge channel and requires to be installed in -devmode as we don't have proper confinement for it in place yet. - -Anbox can be installed from the Ubuntu Store with +Alternatively you can fetch the installer script via ``` -$ snap install --edge --devmode anbox +$ wget https://raw.githubusercontent.com/anbox/anbox-installer/master/installer.sh -O anbox-installer ``` +Please note that we don't support any possible Linux distribution out there +yet. Please have a look at the following chapter to see a list of supported +distributions. -Afterwards run it with +To proceed the installation process simply called ``` -$ anbox +$ anbox-installer ``` -After the first installation the container management service needs -a few minutes to setup the container the first time before it is -available. +This will guide you through the installation process. -Applications can be launched via the launch subcommand of the anbox -binary. For example +**NOTE:** Anbox is currently in a **pre-alpha development state**. Don't expect a +fully working system for a production system with all features you need. You will +for sure see bugs and crashes. If you do so, please don't hestitate and report them! -``` -$ anbox launch --package com.android.settings -``` +**NOTE:** The Anbox snap currently comes **completely unconfined** and is because of +this only available from the edge channel. Proper confinement is a thing we want +to achieve in the future but due to the nature and complexity of Anbox this isn't +a simple task. -When installed as snap there will be also a desktop launcher available -which will directly start the application viewer activity to give -an overview of available Android applications and allows to start -them. +## Supported Linux Distributions + +At the moment we officially support the following Linux distributions: + + * Ubuntu 16.04 (xenial) + +Untested but likely to work: + + * Ubuntu 14.04 (trusty) + * Ubuntu 16.10 (yakkety) + * Ubuntu 17.04 (zesty) + +## Install and Run Android Applications ## Build from source -To build the Anbox runtime itself there is nothing special to know -about. We're using cmake as build system. +To build the Anbox runtime itself there is nothing special to know. We're using +cmake as build system. A few build dependencies need to be present on your host +system: + + * libdbus + * google-mock + * google-test + * libboost + * libboost-filesystem + * libboost-log + * libboost-iostreams + * libboost-program-options + * libboost-system + * libboost-test + * libboost-thread + * libcap + * libdbus-cpp + * mesa (libegl1, libgles2) + * glib-2.0 + * libsdl2 + * libprotobuf + * protobuf-compiler + * lxc + +On an Ubuntu system you can install all build dependencies with the following +command: + +``` +$ sudo apt install build-essential cmake cmake-data debhelper dbus google-mock \ + libboost-dev libboost-filesystem-dev libboost-log-dev libboost-iostreams-dev \ + libboost-program-options-dev libboost-system-dev libboost-test-dev \ + libboost-thread-dev libcap-dev libdbus-1-dev libdbus-cpp-dev libegl1-mesa-dev \ + libgles2-mesa-dev libglib2.0-dev libglm-dev libgtest-dev liblxc1 \ + libproperties-cpp-dev libprotobuf-dev libsdl2-dev lxc-dev pkg-config \ + protobuf-compiler +``` + +Afterwards you can build Anbox with ``` $ mkdir build @@ -83,7 +142,7 @@ $ cmake .. $ make ``` -That will build the whole stack. A simple +A simple ``` $ make install @@ -91,25 +150,51 @@ $ make install will install the necessary bits into your system. +If you want to build the anbox snap instead you can do this with the following +steps: + +``` +$ mkdir android-images +$ cp /path/to/android.img android-images/android.img +$ snapcraft +``` + +The result will be a .snap file you can install on a system supporting snaps + +``` +$ snap install --dangerous --devmode anbox_1_amd64.snap +``` + +## Run Anbox + +Running Anbox from a local build requires a few more things you need to know +about. Please have a look at the ["Runtime Setup"](docs/runtime-setup.md) +documentation. + +## documentation + +You will find additional documentation for Anbox in the *docs* subdirectory +of the project source. + +Interesting things to have a look at + + * [Runtime Setup](docs/runtime-setup.md) + * [Build Android image](docs/build-android.md) + +## Reporting bugs + +If you have found an issue with Anbox, please [file a bug](https://github.com/anbox/anbox/issues/new). + +## Get in Touch + +If you want to get in contact with the developers please feel free to join the +*#anbox* IRC channel on [FreeNode](https://freenode.net/). + ## Copyright and Licensing -Anbox reuses code from other projects like the Android Qemu emulator. -These projects are available in the external/ subdirectory with the -licensing terms included. +Anbox reuses code from other projects like the Android QEMU emulator. These +projects are available in the external/ subdirectory with the licensing terms +included. -The anbox source itself (in src/) is licensed under the terms of -the GPLv3 license: - -Copyright (C) 2016 Simon Fels - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . +The anbox source itself, if not stated differently in the relevant source files, +is licensed under the terms of the GPLv3 license. diff --git a/docs/architecture.png b/docs/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..4dcaf1287c62a6b2e11f6b971f6d648044f2dc35 GIT binary patch literal 29330 zcmbrm1yodD_cx9OiYOx83MeHYCDKZFNJ%3|mq-jXpdeiW0@Bhk3?m&whzLk`!wlUp z3DcoHEv!7t^}wjwE`d4T%{DXZ{EB)J+D3oe7)x;``S&**~$&{=Dj7JmW{ico8^0p zfPq_hcn|OtWnOA~PHoMC-G<#Wj&UHT6ta|856Bg`o++u;*|t2iY^O*IwtSpEcr{5| zuW*x?uK%Yebk6-c%=jHT6mH#>feerjqL(jSyeTO!Vq))-ut20KklsQ;5g^4``O(f! z`Pu}T?eI{p;u(gyQL(P#cW-6qfy+uyi+~W)SE9}fjP&wvGL;2^YJipEwWh^Ay!@=A z08S6aFZZ-$0GvJ;-3HF@xq#D)(i_0}cNK8@tJ~i?e73&=T>aDSZyo+d=WiYUM(1xG z{+j4dx4(7xAM5%5Pv>tF{cB&l>0Mo228M>z1eaU;vFour*Ag9lxBbe$Hy!+8XU7Tu z3f?`{5uz&}3}JP3r+G;xcDA-}*s?7c*H}Fn+MV*)=x zsm(~{O5Ur^t&aUIg20znna5a-NfxV1xeeZ{qQ3gz*&q`Czr;HitieWh2nhe5g8Omr zDOvOZFy@ag)J~`h^GJii7s@P2<$r3aP`Fgq%^<1BYyZ&Jf6>_N@S^_j zY5u6`2fsr=#s9fs;1ZySwVG?vc>gsW&;oQi8#EPd5EMmkP3Rhowk!OZ9&6xRl^XHB zVig8E!4_3Qy*FKXoY>vlWlE29p#A-QeSO>X`^MmO2JaPS$a5JI)tqRW4#As7>3tX12D-(NvQK)Y%n` z87t&I_%)~fPen!H@1`F->soznz23;#+_AhLF}7VpWRrNpV{L&S-%3x3iMf1V%po4KmB+fcPK0i3Cx=eVO7GNB%a)`pZ>T;7` zZ+lh9RI}9z)K%VEg&b_r_Eo+_p@mZA;%(g0TeB`Cmo}qc}H

&^SPH!ZCnM(H8vdzA%pQzL1cgyYwT6}Gk-?S=H(PDueb2 z?xISK+aP*meKl`G^a=G!kh&zv0^lmqF_@9=#IQh8da7w{dF_bHvS-Pt=M>Rcfr*#D zUYV@_sH(C+@*&esaj3+2b+Pf?=1@NY%Fucv=I8N*qv5J^og|LdB}WWWzBU!RzcQGLzk1PF2PCy>&>hj7ii7`&hm$8qrx{R31d)nrT|; z)bVJt6zVaapCEfWKi+6i_Fr8RPON=#DJN52T% zQEz!#2S%ke)ilA(WdXObmm%JmW6f@)*#JQ+4W1ZSOE&0{#(K>rkTY~vrbOu{3hZg4 z6E>&QJdzaJedBdY!DukIk8>+5@7+6@Ri)S5kXkuB?rrK=q~|PerMg#VnL@F< z&LOJ0*Rn=9&8czH;Jc0HN5PIY*Qx3fZ(l83#o?%v$==%SM+x(rWM4^*tM{*{rVnY? z?`P>4I;cfW)&t%37b_k0j|PhAxidr8dWG>xtSwDX&~;lnez8-bP!C-ZSrsq+PHBhz zREI~SO!-%p!);U#4h|P!PuQEE4`I494J&$6E3i-y!fVkBGKO9V?;t4Ygdm$%ZiKv< zTmd2c?GN^e^g3N-IX#RXPT7&hYsFPviyM8GD({x8ySQv}+aTwWGOLq(|G=3MS}Eph zNphHhR+B!fnxT4xRO;{!nQGz@;SEvHdbrLb$Cc$aSY!2GvQg0!FQ>L(#P@l~Z1ut* zr4rrLOkRHpIRD3MxaFv80?A}PG`n`~vccTs4Dhw;`cVwii8{p4Cyw_Odr~s$kYhVLh&Li!^{!!Ku6|FafwWrb%bA3` z>iv-HpX-$Iqi#WrHl@!ns(Fy`F$bPwOA3h!bn?$9{ndi@U1G6t_f$sz!ef+uCVS6e zg0t!H!JyEVHQ@dpaBNmJ71KXDGXKuqITFrd#hvbaPkpkwOWBS)|4~0B%(U4FyqE8Y zYQ}Afr8j$b*F&%UR36)3*cE(+nm8Eaw~DHH-&$Y3X{?)OQ%?100S<*0R}R5C4ePx1 z4P?F_jq26Q9O|z?&I!}2Dr-G2>fJXZgisSzyy~nwL(s*odPh_W8IlxZFb$WbBu)aoLw!xGVeI_*@PvVxv zLO11<(X=Pog8KY2#SVSd?+{RQ$ati22J-xzHdU{$=4)?a_G&~D%`XccC^{@uVA^D6 zfoxdIxk0m`yzsk?@n?B8ejTg&ftW&iwXx%mv`=@{E$ST`SJ+#6@Z z{ri5=M$|JWcq_Ars{g99x};6Zy$i7K=L#6l#QD_5`4bBzxt;PTn0Uepm%oeh+gp6D z+q9|S@A+RvuAFX~On)r^ti)CWg+ZlV?3$=Lvr4%p^s=AL&`F~h)2eq-_)a0M!xdIr zG}g^f^KPpUcZZgRw_u=z#NT<^DZa6X-Q1u_ zOh`DpoXkZ}b@|cV*h)*z15D{>2QRxi#b5e%u3><$=&i@1Djv({84^7Po654!P!{%6 zZ=q+)!6{QiLuXB9!<3F2%E~+j-z2`X@>M)l=W+7!cZG1*uod{Pz1mNF8;;yd@4z0_ zDUCmwp4+7*eCE`!PuMII-^SusFuP1@>oJjL{`(G!p2f<5zs=Oq^;AYoXEb9srHu2b zesAXm53+=e1Xj??$Xz5X)1!R*EF<$-j#*KiGi^G&OFWzBwbM58hs?qLaxzmipL_*N z%I&jfQYmx^M>Gffj~=_|Jr|od6m6h6I4^lPxh_62DfBw&5XEB?H3o20duPMhNsuRk zE-g)}LarDj+yt4o(x`w5>Q@Mer{8o0;)=DN`D2X};`u-(fpOij;}U9k`{c23H%CKU z^;<>U^*pjCHEU<)P_SO3&3+=W%}s7!4t3@}V{%o#l0TL&BB(;hAYT+ zp)5fcb4I-PmgZ0>R6>?#Xl#X&WX~&2l}RLLPpM5ib9#^^yZbjE5z);2m}!iSY&kMLCakS}CV^7H>J3rdG^&9SK^5orNX^Kh91aUbLeaEXb2-dVfDEAK|m_vmwre zfAE7oP9{f@XK3j#oF#SDI=tfz2;;rd_`_U~Hn*vvSl^dBwUt@_MzS>j*j*3wQ8N2A zE1^gFzZUH_z^j|XMAuR*j@m!+L~o{C{8E7^HdK*2?bSJqVzFxRm*3BIJd*nLOieKK z_U)wt7)MoAlfhgfUl&?FAFb;CMIv?Vhf`&hPQFmjGzR3m4Dfrd4{IaZCJVa}+Rm>( z&sw(x+mW~=8WmAYA78wSsOI(k&I&~J)8j_^3-{9V2GZD=;D}t9Kt}5DBlK zylfboac4q&_D%YvCLJTX#=4JeZ%|YS%Jb-0jyeu$zkyKB4n$OqK6(}tI+9fKdSEk4 z@EI)Bb9=gUN^XvnWYEOxIv9J!ziG*`#u_{rzCG$U95?P^Bt8-zO7%qF+hr=fcRte{ zW5|0)*s5_vw0K6%&=HkVX2|`h!|p!FGN_=}77{0*tQ$UPKBkz^JGoL?@=n?6qp%lS z(-F)P4c1Hdt+Uy`V9Ku3tjJ8WRE+nQcZ}~|*_H7~VM&GBED8~~p?N**X8~E& z-YmXzuXwq<{OW|ub4PT`PJ_~q5~jC$6HmpFoql>y`Lko1DWkhdp$~_@k=v4zxabL1 zDf;VlYi;gFw10LvJp&zNxW`CZAFRC}YpUj5AV5HRVg^%+*j;sXryvb+ zPM&br2YTEEsF0eo3Plm9ekvE2w*!KUF|ji-(MYG5&^d*4Co%5n+PDgfGg-x}$*?>c zPeCsv?kj~a+D=GI^QL^aYvldq16=)qdhWsKyl~7-J)sAIPWOC zQ@_sRsOyR@%-Crxv_tp)scUZkFony#K}SQ*i|l?{jYqZza&(ap^UX24*veCi#XD?a z$xvISzU?-{^tkHWLX@b$WI2ocB5bDIHp$R!1!Y>MSVm?QKH@z4F7Lj(65@V^!bNqj z&shq8%C=!O5O@YP($j_M2MLR~IDuVU>m<)BtMY$}H8#ILh?q{x?&qX4ADvnWk5g&} zd?!z)Gqo9Ze_5C&cH?(z<7kqD>mlRToAI&t&0h&!F#)B`@8M9~02#Sq&3HuL`$^U< zS4YF6wBDROk*>A_7pxD78x$0Cg{n)oS~ZF0S*(Z!*w zHBgl2O@qaAu}06XYPrhgN*za}0au*1rKsfnQ$llF^=8O3ci*I zOYfiKjq_m`rpK^O7%Pl!syxxyPwYaig^!}CbSbR(Eks&iMK-C|6={vGl2gua-(=(3 zMwRSf0`*y|Eb~V7jQKrAF?~-e*K(WQ8sb{S0sd@*JERpl(=#7q_n~m6yKHM5v#-{Z z1e8$_|L1+!qa2glW^C;S*0#xp0>VKn%2!{S@7%9w*R(~>+wdQkYL_ChYggq>q7``< ztS!B&Zx!-NshnT zm{<+!Ol>q~cfvDtI@oV)j!z{y7S8Mr1Q>e>=YNs0wJ$CWua(+AUmc$cfA&SP=G(gh z!R`kc96pwfrWStrwND?tw>Vt3jP_Ra;YeGl%0KlwOBbbg;(bE@zO1@DcZlaKAUjRj zN^-Kirx^AG!ovkMF0Z$)oE6n0tD_`0h;)oDzn`k5qC76A21S--t+{l>1@y@1S$6g* z#Q?ErzmZdzPX%~bw;=SfES;gyb0%DNr$Kf7u2R(XPT-kta^YRXd^TSES6e|v%PRSy zL|-Ix;iFZUNn?eLbmyXM>7yVD>C~K(Un@h07qz9m2B*F+my63O!xM!Qdxcof($H~n zN;U20J!go~R|YwP^37oDD)}Dqwxy*f$|>68K971+L?nLai_7Wx@w zy|$cO5Ht;8c#?ent5vjogpo3#>z$qOp}2kTsMF-CBuAbTzluzoax2BUR<8PhkMh@s zfxtGUT&ZS_GPxP0F1S)KX26-rX?XP6XE07I=egr_S26PxN2Kx?PnCGnMO$_UB#CT^ zs!fO5?}$ggxreRQ<4-imKc<_M=)=uuFMGc?$V%1H(lRWEYy3X8Mbo-EWs1&HR2*U|qa5i7e9 zp-6obkG<1)@v%`o#4Wz1rHz^qpF?5F*fj(F>74ufeGZee$YAPzqLWdh?~mz) zdTU8xP99adquBIOaM(CY!sxhrM%mK&LQNdM>5S2<>SfvHb~EntBhIsJNcG_zxv?%G z1h3;{!>sOpb}tVgF3WXT5>J23MBE!8jL=WjQ?4Pa3a`7(7|Hyi6A%2-PJb{76(*42 z;NZX+ea&&Ivgq5l2h7Ziup^ZiMoAL`gR_H7+<86eySA=L2#0EaL-V3i$D%EwYRj5O zJJtW9)BZFKj$S!A+k|ayY>buY1IczhZSC`8f7~(ncox(cZ(1dR+bjQ4g+j44Y%K{T zQCv7k#~)RRw^{YQ@#aT%x0t6Bt-;-gn+`wc3^YUt0FNU^pgrkdbLamai^K* z0QX)CdF?OVxJ^-6S^1P~@C|xvGO+nQAO~w}Yk7HsMT#4b)zY3jBN|#vB_$=B;c!tZ zB0jf4Ud%DlUlQOI3o9$@M&{ybrav%oOEV7BY+cX82iln_^p8$RNDvehjFH4X9|p%} zUTj%w;^?+L;M3bCGlblMdAvnBx$shrs{f!$Elu zc)H7FA%Xn0kjL%Hs;bfPaZWNqgIg9FuC5gwi-UGm1b6Ao1k8KuTvz)tC1Im>oE#if zcK{K|1crx)zhj(d&Gh|g^DE^V!QJbDFEjh)2f6Wu>7sYHaO>*+<^lj$@7<9&Tg!Rz z-~kgC7uRZEy2T6gE@068j0>#-wRB1Uj4NU6{@8=e*4vA~4E`GFMc=ekTttq<}(;>!2xcb2{Ja z0C$uTUcb7$yd0^xb<%B$y)TSm^grjdxG#E_QG%}S^=Ev0UMmpcgq|8(_)S!OMyBCslaw0;_6j0J#YX3HdZ4UOf2x z`SZ6|MPHOQZkF+3h6~h>J;f-wjdn2?ii(O%eCEGy$~~rVb9bM0A2;SmD2BtQH;>f5 zK7CoFjR3Ah5?vNPAfG;c+O4CygWsoef$^<#Tu!<-IaxYLcXs9Bm8GmX4g zymtY61MGqdQ8<2e$>7o~j7IF8?`%}PaCik71VRl(_!DN)z^I{OSwsER);6p8O#Z z$}wX9@vCfOA~0Ap$eZh4Md5gy{gnsBKxNFF;>Z9XV))73q6YuS0B``8igXPy`ai1_ zqCA>147?n&c1abu_(I^D2{7}ALMg_p|0^NvKL-4nVw z*BlSVFPSv>;m@Kk$=AvPmSq30z2eD`1HA6Z{>LsFDMIx}E=k@Km&*Dql?9YBiEaQj z!b?>EmFC_0`@)z3Vnu)P&U?V<_Gf!)0)Tg^(car!F9160AO48R?CEa}U?*l1Kw$do zxq$;f8=!aZj*aZ)UcY=JzVZNI|6f<1ZViT979=^pJ8e+_Euk)dt>w`r2crMtz;%EF z?SBdN%Qq8X*3L`45Td{M^Fa%~xf9)e=bu;rpe6J^;Aa0C`~&*pQtBU!E_H>75Pb7R zWDfDiOEm}p*t7W8R+KJTLwBhLmrnXp_5hKZtDEgkSI+Kzpeh)&Iro!X1Xg*eZSzqQ z*Dp2X)@74C$&{OQrojV2UnTQ%^Q$4-$nL1Z$ic4RhH)3xw9CVwq+G%!5FAuW; zfoXFjn7}ec+&KbCnMFiJO}*Fi0C90MZB3Nrz~Me4g_>3s$t@27DeV=GBg7;!o%=Jy z9UUD3;^ zbP#%b4KR+mc8l2wRdPzoq>Ky(>~W>-@QG5y%X!KVQdx61O?f#VK77c`90;bp6oSvZ z?scdxM#%p_C{oTLMbLiiE3ZX+G<~f1kZa z{tg)rjf=LnHqMf8AZDIxc)WR{RIi&H)=l#?R7-D|4{~k79PRBl@1MTkl4+;IGyk=A zU_I+}Y`UDa4ulYRF9ZM^`-3+z^IUjt`u`l70MQ1p+dm;k_U*r;3e0Q(llw2M1JDmx z^B*L^J>%Cx{|$xst68SuAfZcx?bq{v#4&*D1RDOV?ys=ua@)82y8q)E;L83QefU3P zv>#D`$NevC0?-+-%Yhi||3EYR8*}qv?Popjzk@s~8o;&u6tz}q8NVT1dp1Z7Poze+rM3_wbhPC`7b1FUEgCcKG;X(wAj}bjU8@CN<1xc zISy=gtwzQJM%allwJ)KI*siRJCRHh7oMu}8-|lN z(Mnt^vd{3FC?<`q07B)lodZhTX=$_m*|e}C(<-Q`>7u3}py4fvC}70_ylOh?hE$*= zeHY_EajE1Z$jND2%9mf9CbIs`D?4??xv{Mr2mOQR4$9{-lx&`luC_iNqal3E8XCH$ zLQGR7?WMeUD9MHmkyW4JcX3!1BCuEUGZ-GYM=rrHKRvW z^-@=g59KU<(?Z=qUiGOlH=52Ktkq%f!wiHSqpTJ}=dk|UXC4EA`HjXTtc1qJQtU!N zM(^Wmpw%CntP|@ACyM+-?V`nfGWn-VMBO$f1)-YSo!m(ehEaOq zp=&z%MbcJ~sQ?0@Gqm%eusRsGnt(pub4}`)^{aU`N@FKM;(#rN+kYB*XKECV4c3;E z5i%j61UU+wRgd73aJv_$Q5qj85l<0R4eoLp9AR<$?8fly5Q9 zV}3g6cf8w&wP88A2d_2qi;0dQZt{VMtg<&BwX&Q`7guVy#?&&i?y2vt(PF*zaLde* z;h#5QCnfdG;%bxco^E--2WNnW9$RL2U!knZc=BS(+9sN(CIa>Qx`mf>zm=IP;jwr;qy&D+JcXrGb~-KHdxXPau3`rX5l`^jfTjFOcs1A%~*x{ zo#`BVlWCt3){CSxY&Vao7WL!HU>d38xYRmVs0E%SpOHnS{vK?&Cz=@fE84af`CQ zaNCoCqZoff6VPL}B=mUuqdcxI6g(4MA0J|hJkVE9h5corD+jYM?*j3}bZ_|vgR84C zdW^pA>N>rn-mYNz=vrtIDYRV^9#e_V^HR2o6Yz8UK5QQLM2tn%+X3-J`OJ}Yp%vV2 zP3(t&7Zvlyl)OfNqBFu3p<6OmhrFhieO+rVq}6xf&J0aIPm0w0QY{r3A@MJ|*XxCj zpOJ~3#qW*cPAB@>(HWKEt4Ute{BfiJn^*8L1$fu|Jk>WLD6mCurUbi* zft`ossei~;4B#p63WbwFlpbaAD8awvXeSqK2v`7lj)?++Vrz=xxOPstXzkEY1yDzr z*|w;06iFM$vgha*Dfh0~u9N4n(Ha%XOc7tZ_KIzT?7+oLE?=Z%a+wd8oqgv+26`h? zt#sD4$T`+`MCk2KzC+M2K>ge`2C+vxd+j7Gft%+AJclz0i2Fj8rFM}f4~J&=bP6rD z$TJi6J&r1U$cM;_u~E&~o)417?~Xc@j<$>0iHn?@4XIi0JKRa1MIN;gWZnLVi1lLO z1{c3yD$K}sI3d(Qh2Z;cMZZEGzv_o@c=lLhRM{T9pJtv~U&$bWujy_iPi5kyCf{tH zFJ0^m%mwS+Pgo~zn-y*ZdB)&3vE8XgM|V2jUKlFih;QdyT#(6yAG{uKLSE+~TBKYG zBW0Dqo-DS85JN^cM0aWz8F71zA#-vjweKF@y9qq#eo08U*o*O}6ZfucGe4at_AeY> zKT!zdTVz$w%%X5U8eDAo=Bo)hLnMP{_`$DE5h+)a-_OLy7^sc=qV0;NA*q#~h)UTQ zG0&YUWb-U#z~k2$sRLdOXS<9|qiUULR>{Y^OSw4T{lIn)5>3^UHd11qjBif1C9|ie z`u^uK-QvR;Mkyl8+mdAC9%+zSc-ho<3D>if2A+)X={rh%Q2no^w*?xE&L)$RxT6XE zD&P%o27iX#P)@RjZ*bVD>!vw~?X0iex0Uqg22$aLnG*YJ73+IkQB|VEY2rywxz9u6 z5ofLK^>;OA(GhtO6s$Fjr{{BUYZ20RTIjKgkGE~W@iM4;+ES(cf|fGhK1F?JX4+Fu zPBrrx7@c+_e&mt*gc|71OyYB}?jEURG6_;&&vnG3s{k(ED{|UozWB@E|Kg%)>p41u zAmgCEyXzR+#~E+kqwm|V9=<5bfN6HuGclud0MUywe0|=UCbFWSt}a`9YhJ<20#o_B zF;=l(qU=ZZrkDwM#4q3YetT~%s|7GI=~N9=WWcaTEu+eB{xlGCjPrJeI}IJOmKR9E zwP{QchNR~^sU7S7-}i2Hlew?%ZRE%|6f4FTh+nL+kgRhN7VV^5>~bCur8v_%VD1Vj z3@vqP-KN0Kl7Tx@V$_c%L|aL3JKMXAPKnC5kAfGM)A8SLM`Z~Vqm&X#nT-qj+#nJ+ z)$~hKp6lt;?s3+=FX?($@XA2iI_6WoOyy!iCkW#IUG5=n!`Wdy3@UlXs`@_7E&XnN zf2iFTDM_88`?us|R2H@K+&-nmTnAr~ohjTofX>J0Zl?t)C4B0mzwP11-l3v1d-PRF zvZ-R>Vy7FMlIt&%>XZ43#ck(xVTH0BqDZM}Kb&{Au~;UyG{^Xkb?Lc5t*BGq@P^F# z&T|s6X^wih4nD+VCLJq@lOLeHry1cF%wekynhrB_h5WuLJEWc0Qmh)jd7dkfEm+Oz zX6OH#@*c@8zfo5&g?e!5jw^IF>v`MSI!B-mB)(6w**`gW3Poo^4e2t;;f>q?=CIif z9V?^(!K|X2oSDfG>TI!+_moqI?%FcJaHX3DmIO zZP&(vge`ecQ02bwED<$lfk&v2&FB!1Oz*YjhFJc%s^x9IHiwbU$t2_yxdc-SJY+*x z+{NEx-;q?ifEM3jP@(%;BK74ed^YPce%dWh^HVf54V<`PbEQSk?BcCWXR(b49(rEAmx47!fkHJFf9ttw0^qF2TSyofjMQe(> zPyU0x!Ltp?o)m%JZ=&x?j|Z>GBQUM5@**-acANcCCQTCHIQM|Y742QPlLViTe;=89 z!NvBrxNH4!1wj(GA79n+e0;uyc>gzBiQ0`Lu=w)oek(DzF?uQOJb<~`e|i{`Qgk}E zjx&@`rdXPyRg%;bd{s}omGwbk?)A4KX+f8IZ>j8Nm$~xd=nHIMW0}Lx#l4E2Vz-Ly z_12xwzd!w~U3zX?;l8uko3pW=lKDi>c%*Zttl$3u(*%15WJkYH+x4_!2#5jT@sq83`A~u}irAB!3UpWM@J!>p5BIaPnc*(%EJU z{8mMMYejt(&xWViLH0X!HLl2}ou&zcimC#$5;|DMLBETl>%t-9N%J}+)Z`{u-+Ql~ zw|^Q7zUbE$U(H;M>#>_9&@+k$9nA|yZa85BQ9qh?K8F@w1C@sLH;8gy^v$iZo>d%C zHm}3%h^3n^ww+@b#EUi9xVy@&`_fLw{V&G5^LvzewAsiAgQW6au`?HH7w-lExxy@s z!lovPeW_(~qjhy~5=5Jlhbtx`LJKlVO-=1vC=*}1H_VXsU;$boh~Iic)3Enc_W1EK zb}f6<;^U&};plvBUR|CnQGITx)7VO@^B5Z2g|hd>3|HJBj;x>|MI0%hBVCxRk=!s8 zyrz_2$9b%WBO^`s=}Y%Y3AUy)J>?iRQxWi9PQ)XVZ79~v0;#^6G>;j2<1?fw;WCsv z6R9{^6wFQl`Y`O2YiNF~hudjOyswKx3#~z@WR|Re{3yP=WqM*D_ImLV9N{aWY z(@2w_3Zpt1w|O8Qqm=~x&k_1tYwXh1zMG`f#}n7Qu-D`{H~OkDG^VG$W8Dt2QpKZ% ziOw-iCbKm~E&QVimIsj$k;4Tx>Eziqy+ekELKE*TlnZVZ=>WYz3@V!cHkrN zc}I1he)|;#=B!Ko=G07(Fn*ZvBgr%fY4vdYa)+2(3*OD*|&3Y{t7Bpz3XH(j4iTKsRQFohtB|TS%H+WsYFr$rE z3eE?T&A=8jhuT4YUwrvP?-kKKoFW+-r4bvaNfJ=v5(zjm?fktr zFL%RMoFYzp*(OIyO-40yhuHt56^%y6v#Q$(&@?yWp1uS!#@&fraEGpjL#ZGsmxPd$ zwVW6O0|PAD8HWyb*u6~4q@>W0+;ZLpl3G9(-JUO5CbzmeQ9aQnD@CAH;N`FBi8V%X zEAx|btpY<9TZglr85Zkbn%dx15oW~f$8Vvb^|;OU>2p=(Ul-K^nFn39yo>VfMI-SG zvLgMX?stFZ-#Mb^^V&KYG$=ydi$$M-X^B;*zNSA&XBFC^Rtf4K*8pv8*IPJ8gnFoW zpwn~?h6;M%xY+n<|8cSR3pP~>L)m%iPwH8s)aamz{8c=tPPRTFg9FOf2W>bgX09`y zk)g17_e3T@aM`E(6^ch8^VH!?B^C`cjv|+jZZe$pbTT`At|sKv5b8Va`FMYSu5J+- zp8Hs3?f@oBuzytiokJptEB{L&s zr1CK-PernL`p~OWA7G6*l0XtkKEICMMLF7bNE>p?DXdo3$5lGwZ6rB~W)x%Q1E%u6Sr%1=yn=j>2x|)N6b|O0;IRuWHxPNIb<|i2>!?!^j$+9 zl=S;I2_Z?WW*3PIQ^x0-%_#;0P>odXw2%18-SY0QkV2p!|oh;S-3{s zYPQ#9EtJi*T=hxl;PD=Kv8$4!F4H8oyR*>m+}+#ryH_FANua0iSx;Za8~QKUtL0gd;cj9q?*|17sXmbn0%QdC_%8RqG-5)bwp5wU-f3KDabvP z==qrR&u!Od-06afTwJ|7^>X76LojQ$UQ2_SD%3N~zRjtiJ2z=QE@IGI4YkDF69_t& zLPB${-&H~$Y-BZtUzp-*pJG1-Q7-ej8`yp8avxP+dmd}(IUz7A$e`9eJ;4RyaMMcY zYR#gh#^RHxyHhysNaa=H(>k=cTFU^=gK`;42L z8>k2g35{92yEmn%a?a`JQ4M$UhqSZ$Ym{K&C}A_`T|d%-ec zat!@#1I@21ZNN1c74OCK<#&K831liQ9v4K9rg`W*M+1LhHmrSLk5RYzpLoTaz{FP= zoxf%u&=-lKJub>>WEbwgV)QwjZ!4;xDDcxYV%&SV?kGno8Q`(>DH|#=dR{87<0!utNyEHIzfXO8@lFdXO>r^wxlu!fp`3G z)iPnn-<253xL}Ny%{;D1L9=cfGv$2AkvE#o@u7vwlGVcr(mXh^PO@pCsP|#eoH9ch z-i@7>jC{z^yYE^oh!VBBpS+~?22$xvdqsrXA9yvR@5Lr+bj(QrQD1iA$2{#eN7pY* zS){mm-1&vs#YeM?rXO`8S(CL+pd$y9^ zOC`T+<@bl~pIsXm=@?qfs~GeUVPkTs>DL#sF7frL^*nBh@}W83Tkq#i6T!YG9@;tU z*&&Z|L5OVT?vZ3FyDV1tB@3x7mCTNE4{5sQw(#5<^U`8Po3L`*ZluWXXBvB=jO`Sk z8a$JzH=7lcMxjq=XlBJkyISJ;5oOYkb}t7V#MW zYMRVsi@~twy@@>lS?#^EG`N_Z5i8WeC-QE_MUgas<4v}jj6qD=4#d!&HPu?}K8a>0 zD8pl0)ER+zJx29;P>XS0@^pqx*+dT6qG6!sw^#L>zQXlA=CO|ZboS31{oIulELujb zciNSUQI03fz%AL8(GA?>JO`_=kgoS1j7%<7W8e+VQ=pVGW!Pr0)>ZXVSoT_^xyv)^ z^57k!STTiE$i);@Uk2n}E@h^L;fc3zBnViAcI67E!0DReOJ82!A-%GCYxEGVBYBeP zl7$-{CDUxsh}QX4<$-A;6!01W<+ZD(Qj3hhowiDE6nnOA=A$6lk4SrI4wDA?Dv~BTNPaXZsodgbA_9!>QlD6(~#jriF66)sJcDEoi0qp0{x5@D^z<0ESS(~Sn1O# zyBX_|#V5yaRbB!2&Pl^TZevzX&@);}&A8G?Gv&6I;7IG6;g`n*xw^oB)vAu z$BBKh8FqbA%U=Zdiddzf8BWw$RDxKJm;qy)X!8!E04T4x7gv%pM73WX9%|FU8GpEd znDSb)0d1qM)rdo%olA*2JFWRbA{(?41e5|;&ofbsMzmJnFe7CH#>eahVo-W86B$hw z9XaLm-S-0(k}SmRQR?>Y^3sUAvCo4{{O?>;Q3_v#lvdz!sX;Ig#OyuRZ-5I#^Mbjhaz6GDi8?HmLzoxf1rYlgR%&YZ3rz-eo_d`vxRKndOp`bb znZ^9i~poNxK5-Lycq$qeo8^h43qAd5_svnNyK8=};FFW~26bmGc+tc%^gBiuo-Rw5L z48A(p23?;<)z-<^12lcacbBeJJUQ-3dH6B0eM%1*FHfNs|Dx7y8*+M*ZtA@v#tXOp zc8;jX+?mEr@7MD;RK06$o^@&mrS@7K(D@zvtI$e_zL}SHX#+3UIM%C(4Ph1R!7A*g zr;<}-TQr^wS4cFY_4+SXYh$CZl32s|d9 zxgP7rznDJ@8&cOOl&M!EPzO)ApBJxMQt=v#Zx*tbMCmuu{6 z&t)pRbf?TWdS-Zb%|&PM*EnvneFtZwTuWrEH%SG`1bU zDE|`+ApAZzRN*_bTi>Aj$@XUyA+2!9`8egrGD**;l9D(p$$<_=e_sIo)D}UB+#)E3 zLc!~}1{0yK9|c_Z^0Y1D?w=#Z(4nCjPuH-%v*=$1tMyb_6Z~iAlQ`?0t$={5 z@44;`UxHOqGx+gwXUiZT%H60Q<4QMh{zMI~v^FDi=yz2O*(D5Z&c|MS>78=ZUL7k# zn&#}g_N1pSLo5(p1ggAwQlan?aDhie+Y)>YRZ6%d&g=84g)S%bq>+o@7=_(7v6lYa zas`07^mYKnOrdC4`x~FJmgjS@n8kn9d$a$)6>9&tI zn&F2=uGLMv8SU9DC--j=E_ffPvbOHV0tg!s!k~pQv4KywNZTK8EEuTsui)L|uLm#> zF9DQ_V_aNZxT$A`OYP&{KL_wcY{iB*mofmL6E_e7o9)5H^r9Z;D?-h0=c#z_|-^qH3@mjpZjnHl-9*r*;TmXPdkde_00PEQD z5Y72msHvqzik)~9a_17bLhb>dMIA@{o^K7Iz9SO_Kn4Ibg`1n(_f~wMI{)iBY#ehm zZW@B4r=&cdw9e#x9C{bbW92b%iJ)05b8@&j)$H%jHsU(d0lYb{E^+#a_a)g)(D)}D zbkK(GE`bH0t#~qZKm!XE5&B{kD4O_6Ft!HFm%`w3GTcVBKkm{3+i+qDl6u+bQ78-m zJoNOE44}G@QH}(Ta~yY4L~P6Vl_PH+Z|d>UQRCWoA7fj3e*nJ@V5UIDZ`A_>fDNUk z+##)d%SomZ=ewcs;yzT~Ot=|&S+=$e~Iy4vb7Mn00NW$v=#uW1h; zSLS*AfQiO8sqe{r9L$l&!Ei^-GE0re2p|zgEVheh5s(@Jpt~qs{{G7aRDAydKaj@z zyZYhb@rDhz029nv&ELlVw{`{N`Q5wxQ3U|O@F7d#LJt|>EDD#-vSBcfGRPV}$8FF0 zYY&5(R`)aaKCnkPyQq8IMI>rgY~6w%1_eD$m7PLS5^bfqbd*N-?I3w1Sav4!2e^$kOS#VZcb z@;CF8i1vTbdEBvjp!$YLKs~7<$$&qGi&2LU6TCh>Y+SScbPn zEzG?Mu(v6A@zKoObZ_yGorSpvr=SC#{-Nkl5@#?w@{lcGB{_GJNd|fnawAYAN=l~B ziw76OqwT**ykz9F+_gN~nY7xoutBT5+fVHpkKAGcVz|< z930G#fUWc_+#vXodjO!EE`VCw8Vc3yd%6$2%cPVyRcWi`<|dFH_@cWCkAZ9@>Pjs! z1Ncxgvw!vAv=sN4jV)9o!sipQ9Pq0c;+5~_f6n8;XX^#)q=3L?1bb+&y+b}RX?Xtp zx#!xdJcHNUy@j^JTbC|nZl08$Ufg|SBr7v8ARtnX8GNbkc%Ez*ORSQbMF4hcgH`hM zR^t`G8sU*%7I-_US@);ewelm2t8VOYj{!ehfp-)ki#SgnxX3+sG@`K`hxOvwHzED5Bs|U9vmajZf`{8{FQNDS7$-u0{5D zL(BItXWp54*IDa3>-+~#c6OfK_rC7?{%x1~zIeUysVfDho5JI6Zehz(vyHXc)dfFw z9eMeRZTD1vEQsmdU}Q`f4|};>&;9*r##z^Tuf&+xyY=i*+5%Y4NvA4TXrc=BCL5P% zz2kW>WH#|l(BC&-mS1hdi|AfktUdr(p!MW*bgCo<{4!ysn6wmFX_0G^9;=D}=!D@+ z@5KzQ%9^<&M;L6!I<`GPLZ(cpqkxW%JZF*$fSgWVNO5}*YUqsJdU{4h52bZW5OvGcv)dx2Fo zA}-QF&Uc#V8;r>P z5B705dZGANwS?^A!PvB;fl!Pj2vXPS=%I%d)q7E|*~@$WY@|`g*zTq7iF|c}Nv(Nn zkJif{%b=i8f*=t65Y_)+W*_>3YLQt(B^S2_-{33UJz(ixHIZ9mrpo{oOh8c3ez9XY zKaFh;Y~R9;o}+klY&qGax7YdOh_0qZWdi(wyCpUQ=#1~E7~XmQ#-a4Ks?f(~_2oOEJlliF2Is*UtP4`m>sA02sFs7LpyqP+P zYk}bJmP%j9JLXrAI^>;-hSag)*?8vwdrI`J1>GW;Tn3AsRCLvVNr$=RM`6 z*}?7IHqxYs$As)$Nyc<#9N5LI>4I`>lLUb&pZ?Y}ZIjbwv`V%!O;|-^gLSFy9QI_M zvR;Oisy}~z7T#=?^XlQvvJ30OtF2_7M|9ER8XZc!5B3m`Yy?b@HQ;%RaLu71V$o6M zZY%?G8Co|#%G{k1ehsN|iCV4vI7$s=%=oxZ#OmTnK)`8JW}Mi@1D%&)cjo-rg&*A4 z?Y5Md5&|}C%|0;}1!SVZ6PL=Gp)c$rAiGxPz{bG4W!^7i505L=T<@5Ub<}vLL>jZQ zUAz1VSG_0R9V;t%Si0pMiEkLV8>J|n_ZlLNKiXeE%4pcbZIs?z;&>H&Ycbarqj;5` z_gZ}Gn_IUpU0`W& zrFN)ng*b078)H^{6Ud~mc5h^)0d(~+q`k+i!3yFx>`?+G`0u%NXUcN8q_f@7>^t7Y zFzYE?Wy5g&tsU!6n93DMh269b~}Z6QgnB=*34+xk4$elP`pDOLAATyUa4$s zE8n>8RETdhy^%Ve&WO6lXUrtVt9l=@F(DUNLLhY(awHuN9ebj}uhTt7ZPG5hXHd8= zq9#L~%yBdrb77$_iSGL&z@M+5<8W(8cCpXKLJ0%NDVFua*ewm2PDCb6hCB^WF-sh6%=NcR%+WUJ40)dQU0w1|8?BadjX5Hb^ zKVH;5`P1DyGB;b3-~*?U9ShY=lE}`6@1sE_9E5H4x)S zqet%N1P;|=WFL#jc3_pEvTQe$^Rj^coWL+3Pnb1E(pj#@xf;w2Ywln6cO$|y>?4Oc z%XKyaJ93k^=c?NJJ7{35S1Y6_#o`C4CsUco4*$EKw@poI9f>=z^Z8Ya3#*2fHS$+E z93-?Mo7*AVLri?e^$u#wvoE8+yMqD_TvG~OSH>TE)I%RKBpidCf;=GPMKPsNLppRT zi=4awhxmwp71=zY$yw5KYi4Tv67nT{ioB@Xw?uwJkimv>itY3oR$Ccpb_vrFqR$_7 zMeTpO%67CPSfXQn~df&71XcLK#U=qKg}Oo$x>$aY`8*p^Uc?` zHG({9M%iV3i`P>3nG*T}n*z)d3L-Rm(35q^z=$kc`AK>|?VY+e6erkJFC?%7#^TR& zCU8n^DeL`Az2{EaCS}e_PA>sMDtu|RzkBvUHfOiahps*l07ka6Vbwj)rMfPtSy?Y` zC+9iN*JI;*|4LuzTUpBFmN|j;27N4fp}u(aq4=mr!Ey5)|9rRaKXMyP6J?8IBz@3> zHbe8;CgCgNJbJ8|d)B}d$ISz5!)BQ+QWHuUiBf|e&*cT!T|EvW&^#IshK9)vI`Xiy0X)Eb91at8 zpWoJy79FT?*dOVL0uS2OHr831x3}li5ZIe^udYeIu0Cpxex4p(+xq9Y{I&UOz9pQ? zDRM8fb!b+?&GGkp7N>&~ce}M43{(2duCRZ^g(A6%3h#(1emRs8A2{9}!CumUknQ9$ zY-bnRAKkxa?`&W06D5Y}H}2<4U|FUO;H6KY7x7;@RXg%VT gA%M+IgHrj+WPFZm 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 literal 0 HcmV?d00001 diff --git a/docs/build-android.md b/docs/build-android.md new file mode 100644 index 0000000..7f4b76e --- /dev/null +++ b/docs/build-android.md @@ -0,0 +1,110 @@ +# Build Android Image + +For Anbox we're using a minimal customized version of Android but otherwise +base all our work of a recent release of the [Android Open Source Project](https://source.android.com/). + +To rebuild the Android image you need first fetch all relevant sources. This +will take quite a huge amount of your disk space (~40GB). AOSP recommends at +least 100GB of free disk space. Have a look at [their](https://source.android.com/source/requirements.html) pages too. + +In general for building the Anbox Andorid image the instructions found on [the pages +from the AOSP project](https://source.android.com/source/requirements.html) apply. +We will not describe again here of how to build the Android system in general but +only focus on the steps required for Anbox. + +## Fetch all relevant sources + +First setup a new workspace where you will download all sources too. + +``` +$ mkdir $HOME/anbox-work +``` + +Now initialize the repository by download the manifest and start fetching +the sources: + +``` +$ cd $HOME/anbox-work +$ repo init -u https://github.com/anbox/platform_manifests.git -b anbox +$ repo sync -j4 +``` + +This will take quite some time depending on the speed of your internet connection. + +## Build Android + +When all sources are successfully downloaded you can start building Android +itself. Initialize the build by + +``` +$ lunch anbox_desktop_x86_64-userdebug +``` + +The complete list of supported build targets: + + * anbox_desktop_x86_64-userdebug + * anbox_desktop_armv7a_arm-userdebug + * anbox_desktop_arm64-userdebug + +Now build everything with + +``` +$ make -j8 +``` + +Once the build is done we need to take the results and create an image file +suitable for Anbox. + +``` +$ cd $HOME/anbox-work/anbox +$ scripts/create-package.sh \ + $PWD/../out/target/product/x86_64/ramdisk.img \ + $PWD/../out/target/product/x86_64/system.img +``` + +This will create an *android.img* file in the current directory. + +With this, you are now able to use your custom image within the Anbox runtime. + +## Run Anbox with self build android.img + +If you have Anbox installed on your system you need to stop it first. If you used +the installer script and the snap you can do this via + +``` +$ initctl stop anbox +$ sudo systemctl stop snap.anbox.container-manager +``` + +It is important that you stop both, the container manager and the session manager. + +Once both services are stopped you can start the container manager with your +custom android.img file by running + +``` +$ datadir=$HOME/anbox-data +$ mkdir -p $datadir/rootfs +$ sudo anbox container-manager \ + --android-image=/path/to/android.img \ + --data-path=$datadir +``` + +This will start the container manager and setup the container rootfs inside the +specified data path. + +``` +$ ls -alh $HOME/anbox-data +total 20K +drwxrwxr-x 5 ubuntu ubuntu 4,0K Feb 22 08:04 . +drwxrwxr-x 16 ubuntu ubuntu 4,0K Feb 22 08:04 .. +drwxr-xr-x 2 100000 100000 4,0K Feb 22 08:04 cache +drwxr-xr-x 2 100000 100000 4,0K Feb 22 08:04 data +drwxr-xr-x 2 root root 4,0K Feb 22 08:04 rootfs +``` + +**NOTE:** If you look into the $HOME/anbox-data/rootfs directory you won't see +anything as the container manager spawns up a private mount namespace which +prevents anything from the outside to see its mount points. + +The *cache* and *data* directories are bind-mounted into the rootfs at *rootfs/data* +and *rootfs/cache*. diff --git a/docs/runtime-setup.md b/docs/runtime-setup.md new file mode 100644 index 0000000..8f07eeb --- /dev/null +++ b/docs/runtime-setup.md @@ -0,0 +1,35 @@ +# Overview + +The Anbox runtime consists mainly of two separate instances: + + * container manager + * session manager + +The container manager has the job of managing the container setup and maintenance +during its lifetime. It has the responsibility to start the LXC environment we're +using to run the Android system. + +The session manager runs inside the session of a user logged into the Linux system. +It will communicate over several sockets with the Android instance running inside +the container and provide integration with the Linux system. It also acts as a +multiplexer to map Android applications into single windows on the desktop +environment. Currently all application windows are owned by the same process +(the session manager). The application logic itself is still in a separate process +inside the Android container. + +The following picture shows an overview over the architecture: + +![Anbox architecture](architecture.png) + +## Application Mapping + +Android applications are mapped into single windows within the desktop environment. +This is achieved by plugging into the Android hwcomposer HAL module which receives +a set of layers to composite on a screen. Anbox tells SurfaceFlinger through its +hwcomposer implementation to get a layer for each application and combines this with +additional information it receives from the Android WindowManager to map individual +layers to applications. For more details please look into the implementation at + + * android/hwcomposer + * src/anbox/graphics/layer_composer.cpp + * src/anbox/wm/manager.cpp