diff options
-rw-r--r-- | README.md | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..314596f --- /dev/null +++ b/README.md @@ -0,0 +1,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 |