Bosch MEMS Android HAL

1. Introduction

The MEMS Android HAL (Hardware Abstraction Layer) implementation shall be used with the Bosch MEMS Android HAL driver.

1.1 Architecture Overview

       Android Apps
           |
       Android HAL
           |
     Bosch Sensor HAL
           |
~~~~~~~~~~~~~~~~~~~~~~~~~~~
    sysfs       dev
      \          /
     iio-subsystem
           |
      bosch-driver
           |
~~~~~~~~~~~~~~~~~~~~~~~~~~~
         Hardware

2. Prerequisites

Important

Building the Android platform requires at least 32 GB RAM. The download and build process can take several hours and consumes approximately 300 GB of disk space.

It is recommended to use the following version: android-13.0.0. All the Android distributions provide the platform and kernel in 2 different repositories. Therefore we need to firstly create 2 working folders for both platform and kernel.

  • download kernel source

  • go to the kernel folder

repo init -u https://android.googlesource.com/kernel/manifest -b common-android13-5.15
repo sync
  • download platform source

  • go to the platform folder

repo init -u https://android.googlesource.com/platform/manifest -b android-13.0.0_r75 --depth=1
curl -o .repo/local_manifests/manifest_brcm_rpi4.xml -L https://raw.githubusercontent.com/raspberry-vanilla/android_local_manifest/android-13.0/manifest_brcm_rpi4.xml --create-dirs
curl -o .repo/local_manifests/remove_projects.xml -L https://raw.githubusercontent.com/raspberry-vanilla/android_local_manifest/android-13.0/remove_projects.xml
repo sync

3. Integrate Linux driver into Android Kernel

3.1 Preparation for build

Go to the “common” folder. This is the root folder of the kernel source. We use smi230 Linux driver as example.

  • copy the Linux driver in drivers/iio/imu

  • add source “drivers/iio/imu/smi230/Kconfig” in Kconfig

  • add obj-y += smi230/ in Makefile

Activate Sensor in kernel

Now we start menuconfig to activate sensor driver.

  • load the standard kernel configuration for your hardware. Dependent on the HW, you can find the stand configuration under build.config.xxx. Example: for the Qualcomm db845c board, the standard configuration is db845c_gki_defconfig defined in build.config.db845c. If you go to arch/arm64/configs the db845c_gki_defconfig is not there. This need to be firstly created by scripts/kconfig/merge_config.sh -m -r arch/arm64/configs/gki_defconfig arch/arm64/configs/db845c_gki.fragment. This will create .config at the android root folder. Rename to db845c_gki_defconfig and copy to arch/arm64/configs/

  • load the standard kernel configuration for your hardware. make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- db845c_gki_defconfig

  • start menuconfig to activate sensor driver make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig activate the sensor driver , save and exit.

<*>Industrial I/O support  --->
            Inertial measurement units  --->
                    <*> Bosch Sensor SMI230 Inertial Measurement Unit

3.2 Extend device tree

Extend the device tree with the sensor entries. This part is very HW specific. Please consult your HW vendor, how to do it properly for your HW.

If using spi, add the following device tree entry to spi sub tree.

smi230acc@0 {
    compatible = "bosch,smi230acc";
    spi-max-frequency = <10000000>;
    reg = <0>;
    interrupt-parent = <&gpio>;
    interrupts = <26 1>; /* IRQ_TYPE_EDGE_RISING */
    interrupt-names = "ACC_INT";
};
smi230gyro@1 {
    compatible = "bosch,smi230gyro";
    spi-max-frequency = <10000000>;
    reg = <1>;
    interrupt-parent = <&gpio>;
    interrupts = <20 1>; /* IRQ_TYPE_EDGE_RISING */
    interrupt-names = "GYRO_INT";
};

If using i2c, add the following device tree entry to i2c sub tree.

smi230acc: smi230acc@18 {
            compatible = "bosch,smi230acc";
            reg = <0x18>;
            interrupt-parent = <&gpio>;
    interrupts = <26 1>; /* IRQ_TYPE_EDGE_RISING */
            interrupt-names = "ACC_INT";
            status = "okay";
    };
smi230gyro: smi230gyro@68 {
            compatible = "bosch,smi230gyro";
            reg = <0x68>;
            interrupt-parent = <&gpio>;
    interrupts = <20 1>; /* IRQ_TYPE_EDGE_RISING */
            interrupt-names = "GYRO_INT";
            status = "okay";
    };

3.3 Build and replace the kernel

Now build the kernel make -j6 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs

When the build process finished, we need to replace the prebuilt kernel with our new built kernel. This can be done in 2 different ways

  • export TARGET_PREBUILT_KERNEL=”Path to my zImage” and then build the platform.

  • find out the location of the prebuilt kernel in $(ANDROID_ROOT)/device/<my device>/device.mk and copy and replace the prebuilt kernel with our new built kernel

4. Integrate Sensor HAL into Android Platform

In the last section we extended the Android kernel with our sensor driver. Now we need to integrate the sensor HAL into the Android platform.

4.1 Preparation for build

  • create folder $(ANDROID_ROOT)/hardware/bosch/sensors and copy all the sensor HAL source code there.

  • open $(ANDROID_ROOT)/device/<my device>/device.mk and add the following content dependent on which HAL type you are going to use.

Important

Be careful with the HAL Type and your Android version. HIDL HALs is not supported any more from Android 14. If you use Android 14 or above, only the AIDL HALs shall be used.

# For sensor hal 2.0
PRODUCT_PACKAGES += android.hardware.sensors@2.0-service.bosch

# For sensor hal 2.1
PRODUCT_PACKAGES += android.hardware.sensors@2.1-service.bosch

# For sensor hal AIDL
PRODUCT_PACKAGES += android.hardware.sensors@aidl-service.bosch

# For sensor multi hal 2.X
PRODUCT_PACKAGES += android.hardware.sensors@2.X-service.multihal.bosch
PRODUCT_COPY_FILES += hardware/bosch/sensors/multihal/common/hals.conf:$(TARGET_COPY_OUT_VENDOR)/etc/sensors/hals.conf

# For sensor multi hal AIDL
PRODUCT_PACKAGES += android.hardware.sensors@aidl-service.multihal.bosch
PRODUCT_COPY_FILES += hardware/bosch/sensors/multihal/common/hals.conf:$(TARGET_COPY_OUT_VENDOR)/etc/sensors/hals.conf

4.2 Build Sensor HAL

Now we can build the system. Prepare the build environment

source build/envsetup.sh

lunch aosp-your-lunch-choice-userdebug

There is dependency between the SW module. To build the sensor HAL we need to firstly build the dependencies.

    mmma hardware/bosch/sensors/hwctl
    mmma hardware/bosch/sensors/core
    mmma hardware/bosch/sensors/sensors
    make bootimage systemimage vendorimage -j$(nproc)

Check if the HAL service binary is built properly under $(ANDROID_ROOT)/out/target/product/rpi4/vendor/bin/hw

4.3 Extend sepolicy

In Android without explicit permission, the execution is always forbidden.

Add the following content in $(ANDROID_ROOT)/device/<my device>/sepolicy/file_contexts

#Bosch Sensor HAL

/vendor/bin/hw/android\.hardware\.sensors@2\.0-service\.bosch u:object_r:hal_sensors_default_exec:s0

/vendor/bin/hw/android\.hardware\.sensors@2\.1-service\.bosch u:object_r:hal_sensors_default_exec:s0

/vendor/bin/hw/android\.hardware\.sensors@aidl-service\.bosch u:object_r:hal_sensors_default_exec:s0

/vendor/bin/hw/android\.hardware\.sensors@2\.X-service\.multihal\.bosch u:object_r:hal_sensors_default_exec:s0

/vendor/bin/hw/android\.hardware\.sensors@aidl-service\.multihal\.bosch u:object_r:hal_sensors_default_exec:s0

make bootimage systemimage vendorimage -j$(nproc)

4.3 Check Execution

adb connect
adb shell
service list | grep sensor

The android.hardware.sensors.ISensors.default service shall be started properly.