Clone this repo:

Branches

  1. 832ab8b libkdbinder: Add a README with build instructions by Pierre Langlois · 8 years ago master
  2. 7e800f0 libkdbinder: Update copyright year to 2016 by Pierre Langlois · 8 years ago
  3. 75c67df libkdbinder: Add a KDBUS version of the service manager by Pierre Langlois · 8 years ago
  4. 999315a libkdbinder: Support the latest version of KDBUS by Pierre Langlois · 8 years ago
  5. 80f5f70 libkdbinder: Remove an unused parameter by Pierre Langlois · 8 years ago

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 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.

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, it is called "juno-uefi.zip".

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 (but any AArch64 toolchain should be just as fine, modify CROSS_COMPILE accordingly).

$ 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