aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 314596fad363d449c1b0f62e907e5871a0539e45 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
KDBinder
========

This library is a proof of concept replacement for `libbinder`, implementing a
subset of its API on top of KDBUS. `libbinder` is an interface between
applications and the binder driver in the kernel. `libkdbinder` follows the same
principle, but allowing us to replace the binder driver by KDBUS.

Note that this work is experimental.

Binder API
----------

The current state of the Binder API that this library implements is documented
in `binder.md`.

We are *aiming* to implement as much of the API so that surfaceflinger can run
along with bootanimation. However, this is a work in progress.

Low-level KDBUS layer
---------------------

`libkdbinder` implements its own internal interface for KDBUS, the details of
this API are documented in `kdbus.md`.  The API tries to match how KDBUS works
so it is recommended to have a look at the high level documentation of KDBUS.

Build instructions
------------------

Throughout these instructions, we'll assume the `${ANDROID_TREE}` environment
variable points to where Android is checked out.

KDBinder was tested on the JUNO r2 development platform with a release of
Android M from Linaro.

### Integrating KDBUS and KDBinder in the Android tree

First of all, download the Android tree from linaro:

    $ cd ${ANDROID_TREE}
    $ repo init -u https://android-review.linaro.org/platform/manifest -b android-6.0.1_r16 -g "default,device,arm"
    $ cd .repo
    $ git clone git://android.git.linaro.org/platform/manifest.git -b linaro-marshmallow local_manifests

We need to include KDBUS and KDBinder to the tree. We can do this by adding a
local manifest file that points to both projects. The manifest will instruct
`repo` to fetch the out-of-tree KDBUS kernel module and KDBinder.

TODO: Add the `linaro-android` remote to this manifest snippet.

    $ cat > local_manifests/kdbinder.xml <<-EOF
	<?xml version="1.0" encoding="UTF-8"?>
	<manifest>
	  <remote name="systemd" fetch="https://github.com/systemd/" />
	  <project path="external/kdbus" name="kdbus" remote="systemd" revision="master" />
	  <project path="frameworks/kdbinder" name="platform/external/kdbinder" remote="linaro-android" revision="master" />
	</manifest>
	EOF

Download the Android tree.

    $ cd ${ANDROID_TREE}
    $ repo sync -j${N_JOBS}

KDBUS requires a recent enough kernel, and the stable kernel we have checked out
is based on 3.18 which is too old. We will use the latest kernel instead, as of
the 11th of February.

    $ cd kernel/linaro/armlt
    $ git checkout latest-armlt-20160211

Finally, the default configuration does not allow kernel modules.  Enable it in
"linaro/configs/android.conf" by setting "CONFIG_MODULES" to "y".

### Build and install the Android filesystem

We are now ready to build the new kernel and Android filesystem. Watch out for
the sudo prompt at the end (needed to temporarily mount the system image), it
may time out after some time.

    $ source build/envsetup.sh
    $ lunch juno-userdebug
    $ make -j${N_JOBS} selinuxtarballs

You may encounter errors (unsupported relocations) when linking ART
executables. This seem to be a problem specific to Clang, recompile with GCC
instead:

    $ rm -rf out/host/linux-x86/obj{,32}/SHARED_LIBRARIES/*art*
    $ make -j${N_JOBS} selinuxtarballs WITHOUT_HOST_CLANG=true

We need to burn the filesystem onto a USB flash drive. Download the latest
`linaro-image-tools` from this [git repository][1] and run the following
commands (replace `sdX` with the drive's device node):

    $ cd ${ANDROID_TREE}/out/target/product/juno
    $ sudo linaro-image-tools/linaro-android-media-create \
        --mmc /dev/sdX --dev vexpress \
        --systemimage system.img --userdataimage userdata.img \
        --boot boot.tar.bz2

You may now connect the USB drive to the JUNO board.

[1]: https://git.linaro.org/ci/linaro-image-tools.git

### Setting up the JUNO board and booting to Android

We are going to install a UEFI firmware on the juno board. You may download it
[here][2], it is called "juno-uefi.zip".

[2]: https://community.arm.com/docs/DOC-10804#jive_content_id_41_Prebuilt_configurations

Power on the JUNO board with a serial cable connected and press enter to stop
auto boot. Then execute the following commands:

    Cmd> flash
    Flash> eraseall
    Flash> exit
    Cmd> usb_on

You should now see the JUNO board come up as a USB storage device. Mount it,
remove *all* of its content and replace it with the content of "juno-uefi.zip".
Make sure you keep the directory structure. For instance:

    # mount /dev/sdc1 /mnt
    # rm -r /mnt/*
    # unzip /path/to/juno-uefi.zip -d /mnt/

Then, we have to copy our kernel, device tree and ramdisk:

    # cp ${ANDROID_TREE}/out/target/product/juno/boot/kernel /mnt/SOFTWARE/Image
    # cp ${ANDROID_TREE}/out/target/product/juno/boot/juno-r2.dtb /mnt/SOFTWARE/juno-r2.dtb
    # cp ${ANDROID_TREE}/out/target/product/juno/ramdisk.img /mnt/SOFTWARE/ramdisk.img

Finally, we need to instruct UEFI to boot our kernel. You should find the
following file in "/mnt/SOFTWARE":

    # cat /mnt/SOFTWARE/startup.nsh
    echo -off
    echo Juno startup.nsh from NOR flash
    echo Example command to start the kernel:
    echo norkern dtb=board.dtb initrd=ramdisk.img console=ttyAMA0,115200n8 root=/dev/sda2 rw rootwait earlyprintk=pl011,0x7ff80000 debug user_debug=31 androidboot.hardware=juno loglevel=9 sky2.mac_address=0xAA,0xBB,0xCC,0xDD,0xEE,0xFF

Append this file with the following line:

    norkern dtb=board.dtb initrd=ramdisk.img console=ttyAMA0,115200n8 root=/dev/sda2 rw rootwait earlyprintk=pl011,0x7ff80000 debug user_debug=31 androidboot.hardware=juno loglevel=9 sky2.mac_address=0xAA,0xBB,0xCC,0xDD,0xEE,0xFF selinux=0

We are now ready to boot to Android. Make sure you've issued a "sync" before
umounting the JUNO's USB storage device. Plug in the USB flash drive with the
Android file system and enter reboot the board:

    Cmd> reboot

If it all went well, you should have booted to a shell on the Android
filesystem. Make sure you have connected an ethernet cable to the GigaBit
ethernet port, just below the JTAG port. Network may take a few minutes to
become ready.

Testing KDBUS and KDBinder
--------------------------

We will need to send files over to the board with adb. However, the `/system`
partition is mounted as read-only by default so we remount it as read-write.

    $ adb connect X.X.X.X
    $ adb remount

### Building and installing KDBUS

The KDBUS out-of-tree module needs to be built against the kernel. We are using
the bare metal toolchain from [linaro][3] (but any AArch64 toolchain should be
just as fine, modify `CROSS_COMPILE` accordingly).

[3]: https://releases.linaro.org/components/toolchain/binaries/latest-5.1/aarch64-elf/gcc-linaro-5.1-2015.08-x86_64_aarch64-elf.tar.xz

    $ cd ${ANDROID_TREE}/external/kdbus
    $ export ARCH=arm64
    $ export CROSS_COMPILE=aarch64-none-elf-
    $ make KERNELDIR=${ANDROID_TREE}/out/target/product/juno/obj/kernel module

Then you may upload and load KDBUS into the running kernel:

    $ adb push ipc/kdbus/kdbus.ko /system/kdbus.ko
    $ adb shell
    # insmod /system/kdbus.ko
    # mount -t kdbusfs kdbusfs /sys/fs/kdbus

### Building, uploading and testing KDBinder

KDBinder was checked out in "frameworks/kdbinder" by repo. All we have to do
now is build it and upload it to the target.

Build `libkdbinder` and its test-suite:

    $ cd ${ANDROID_TREE}/frameworks/kdbinder/libs/kdbinder
    $ mm

Build the `kdbus_servicemanager` utility:

    $ cd ${ANDROID_TREE}/frameworks/kdbinder/cmds
    $ mm

And upload everything to the target:

    $ adb sync

For KDBinder to work, we need this service to run in the background. Leave adb
shell running or background it, there doesn't seem to be a clean way to
daemonize an arbitrary process from adb:

    $ adb shell
    # kdbus_servicemanager &

Now you should be able to successfully run the tests on the target!

    $ adb shell
    # /data/nativetest64/kdbinderTest/kdbinderTest
    # /data/nativetest64/kdbinderKDBUSTest/kdbinderKDBUSTest

### binderAddInts benchmark running with KDBUS

The KDBinder tests we have run only make sure that the library itself is
working. However, the interesting part is that `libkdbinder` aims to be a
drop-in replacement for `libbinder`. This means we can choose to build
packages depending on `libbinder` with `libkdbinder` instead.

At the moment, support for this is very limited. But here is a working example
for the `binderAddInts` benchmark.

Run the benchmark on the target. You may need to make it explicitly executable.

    $ adb shell
    # chmod +x /data/nativebenchmarks/binderAddInts
    # /data/nativebenchmarks/binderAddInts

Let's create a version using `libkdbinder` called `kdbus_binderAddInts`!

Navigate to `binderAddInts`:

    $ cd ${ANDROID_TREE}/system/extras/tests/binder/benchmarks

Edit the `Android.mk` file and append the following:

    include $(CLEAR_VARS)
    LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk

    LOCAL_MODULE_TAGS := eng tests
    LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativebenchmark

    LOCAL_STATIC_LIBRARIES += \
        libtestUtil

    LOCAL_SHARED_LIBRARIES += \
        libutils \
        liblog \
        libkdbinder

    LOCAL_C_INCLUDES += \
        system/extras/tests/include \
        frameworks/base/include \
        frameworks/kdbinder/include/kdbinder

    LOCAL_MODULE := kdbus_binderAddInts
    LOCAL_SRC_FILES := binderAddInts.cpp

    include $(BUILD_EXECUTABLE)

This is building an executable from the same source as the binder version, but
this time it builds against `libkdbinder`.

Build, upload and run:

    $ mm
    $ adb sync
    $ adb shell /data/nativebenchmark/kdbus_binderAddInts