============================== 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 -------------------------------- .. code-block:: none Android Apps | Android HAL | Bosch Sensor HAL | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ sysfs dev \ / iio-subsystem | bosch-driver | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Hardware 2. Prerequisites ================ - Set up an Android build environment as described in the `Set up for Android Open Source Project (AOSP) documentation `_ - Download the Android source tree as described in the `Download Android Source documentation `_ .. 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 .. code-block:: repo init -u https://android.googlesource.com/kernel/manifest -b common-android13-5.15 repo sync - download platform source - go to the platform folder .. code-block:: 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//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//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//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.