Introduction
We have an official PN7160/PN7220 Android 15 porting guide (PN7160/PN7220 – Android 15 porting guide). But the patches only for Android 15 AOSP r1 (android-15.0.0_r1). If customer want to porting to the newer release of AOSP, there will have many errors during the source code compiling. This document is for customer reference to solve the error one by one.
NOTE : All the modifications are just for reference. They are NOT a NXP official patches for the newer release of AOSP porting. So the modifications may not be the best solution. Customer please base on their needs to modify the AOSP source code. This is not for production. Customer still need to perform full testing after the porting.
Hardware boards:
i.MX8MN EVK (i.MX 8M Nano Evaluation Kit | NXP Semiconductors)
PN7160 EVK (OM27160| Development Kits for PN7160 Plug'n Play NFC Controller | NXP Semiconductors)
The connection between i.MX8MN EVK and PN7160 OM29110ARD-B
i.MX8M Nano EVK
pin
PN7160
pin
3.3V
J1003-1
VDD(3.3v)
J1-4
5V
J1003-2
VBAT (5v)
J1-5
I2C3 SDA
J1003-3
SDA
J2-2
I2C3 SCL
J1003-5
SCL
J2-1
GPIO3_22
J1003-37
IRQ
J2-10
GPIO3_21
J1003-38
REQ
J4-2
GND
J1003-39
GND
J1-6
GPIO3_20
J1003-40
VEN
J4-1
Build the Android for i.MX8MN EVK
The i.MX Android BSP that I used is Android 15.0.0_2.0.0 (L6.12.20_2.0.0 BSP). It could be downloaded from here: Android OS for i.MX Applications Processors | NXP Semiconductors
1. Download the "Documentation" and the "Install Source Package".
2. Follow the steps in Android User's Guide to build the Android BSP for i.MX8MN EVK first.
According to the android_build/.repo/manifests/aosp-android-15.0.0_2.0.0.xml, you will see the AOSP version is android-15.0.0_r32.
Reference documents for porting:
PN7160/PN7220 – Android 15 porting guide
Porting PN7160 to Android 14 on i.MX8M Nano board
Now, we start the porting:
1. Kernel Driver
To establish connection with the PN7220 or PN7160, the Android stack uses the nxpnfc kernel driver. You could download the driver from github below:
nfcandroid_platform_drivers/drivers at br_ar_16_comm_infra_dev · nxp-nfc-infra/nfcandroid_platform_d...
The command is :
git clone "https://github.com/nxp-nfc-infra/nfcandroid_platform_drivers.git" -b br_ar_16_comm_infra_dev
There is driver for Kernel 6.6 and 6.12. So, please download the correct one for your porting. For example, the kernel in i.MX Android BSP Android 15.0.0_2.0.0 is 6.12. So I will use the 6.12 driver for my porting.
In your porting, make sure the PATH in Makefile and Kconfig files are setting properly.
For example in my porting:
android_build/vendor/nxp-opensource/kernel_imx/drivers/nfc$ tree
.
├── Kconfig
├── Makefile
└── pn7160
├── common.c
├── common.h
├── i2c_drv.c
├── i2c_drv.h
├── Kbuild
├── Kconfig
├── Makefile
├── spi_drv.c
└── spi_drv.h
1 directory, 11 files
The contents of Kconfig and Makefile:
android_build/vendor/nxp-opensource/kernel_imx/drivers/nfc$ cat Makefile
#
# Makefile for the kernel nfc device drivers.
#
obj-y += pn7160/
android_build/vendor/nxp-opensource/kernel_imx/drivers/nfc$ cat Kconfig
source "drivers/nfc/pn7160/Kconfig"
2. Adding the "nxpnfc" to the i.MX8MN EVK device tree file
&i2c3 {
clock-frequency = <100000>;
pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c3>;
pinctrl-1 = <&pinctrl_i2c3_gpio>;
scl-gpios = <&gpio5 18 GPIO_ACTIVE_HIGH>;
sda-gpios = <&gpio5 19 GPIO_ACTIVE_HIGH>;
status = "okay";
nxpnfc@28{
compatible = "nxp,nxpnfc";
reg = <0x28>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_nfc>;
nxp,nxpnfc-irq = <&gpio3 22 0>;
nxp,nxpnfc-ven = <&gpio3 20 0>;
nxp,nxpnfc-fw-dwnld = <&gpio3 21 0>;
};
The GPIO settings in the IOMUXC:
&iomuxc {
pinctrl_nfc: nfcgrp {
fsl,pins = <
MX8MN_IOMUX_SAI5_RXC_GPIO3_IO20 0X19 // VEN
MX8MN_IOMUX_SAI5_RXD0_GPIO3_IO21 0X19 // FW-DWNLD
MX8MN_IOMUX_SAI5_RXD1_GPIO3_IO22 0X19 // IRQ
>;
};
3. Modify the imx8mn_gki.fragment
File: android_build/vendor/nxp-opensource/kernel_imx/arch/arm64/configs/imx8mn_gki.fragment
Add the "CONFIG_NXP_NFC_I2C=m" into the imx8mn_gki.fragment
4. Add the settings in your corresponding board configuration files in Android
- Go to the android_build/device/nxp/imx8m/evk_8mn/
- Modify the BoardConfig.mk.
# selinux permissive
+ BOARD_KERNEL_CMDLINE += androidboot.selinux=permissive
BOARD_SEPOLICY_DIRS := \
$(CONFIG_REPO_PATH)/imx8m/sepolicy \
$(IMX_DEVICE_PATH)/sepolicy \
+ vendor/nxp/nfc/sepolicy \
+ vendor/nxp/nfc/sepolicy/nfc
- Add the "nxpnfc_i2c.ko" to the ShareBoardConfig.mk. Make sure the path and the filename are correct.
$(KERNEL_OUT)/drivers/net/phy/realtek.ko \
$(KERNEL_OUT)/drivers/pps/pps_core.ko \
$(KERNEL_OUT)/drivers/ptp/ptp.ko \
$(KERNEL_OUT)/drivers/net/ethernet/freescale/fec.ko
+ $(KERNEL_OUT)/drivers/nfc/pn7160/nxpnfc_i2c.ko
endif
$(KERNEL_OUT)/drivers/trusty/trusty-core.ko \
$(KERNEL_OUT)/drivers/trusty/trusty-log.ko \
$(KERNEL_OUT)/drivers/trusty/trusty-ipc.ko \
$(KERNEL_OUT)/drivers/trusty/trusty-virtio.ko \
+ $(KERNEL_OUT)/drivers/nfc/pn7160/nxpnfc_i2c.ko
else
BOARD_VENDOR_RAMDISK_KERNEL_MODULES += \
$(KERNEL_OUT)/drivers/input/touchscreen/goodix_ts.ko \
$(KERNEL_OUT)/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.ko
Endif
- Add the following to the Compatibility_matrix.xml
<compatibility-matrix version="1.0" type="device">
<hal format="native" optional="false">
<name>netutils-wrapper</name>
<version>1.0</version>
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.emvco</name>
<version>1</version>
<interaface>
<name>IEmvco</name>
<instance>default</instance>
</interface>
</hal>
</compatibility-matrix>
- Add the following to the device_framework_matrix.xml
<compatibility-matrix version="1.0" type="framework">
<hal format="aidl" optional="true">
<name>nxp.hardware.secureime</name>
<version>1</version>
<interface>
<name>ISecureIME</name>
<instance>default</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
<name>nxp.hardware.imx_dek_extractor</name>
<version>1</version>
<interface>
<name>IDek_Extractor</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.nxp.nxpnfc</name>
<version>2.0</version>
<interface>
<name>INxpNfc</name>
<instance>default</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.emvco</name>
<version>1</version>
<interface>
<name>IEmvco</name>
<instance>default</instance>
</interface>
</hal>
</compatibility-matrix>
- Add the following to the evk_8mn.mk
# ------nfc-------
$(call inherit-product, vendor/nxp/nfc/device-nfc.mk)
$(call inherit-product, vendor/nxp/emvco/device-emvco.mk)
PRODUCT_PACKAGES += \
android.hardware.nfc-service.nxp
PRODUCT_PACKAGES += \
com.nxp.emvco \
com.nxp.nfc \
nfc_nci_nxp_pn72xx
- Add the nxpnfc_i2c in init.rc
# Grant permission for fetching available_pages info of statsd
chown system system /proc/pagetypeinfo
chmod 0440 /proc/pagetypeinfo
exec u:r:vendor_modprobe:s0 -- /vendor/bin/modprobe -a -d \
/vendor/lib/modules nxpnfc_i2c
write /sys/power/wake_lock nosleep
on post-fs-data && property:vendor.skip.charger_not_need=0
setprop vold.post_fs_data_done 1
- Add nxpnfc to ueventd.nxp.rc
/sys/devices/virtual/thermal/thermal_zone* trip_point_0_hyst 0660 system system
/sys/devices/virtual/thermal/thermal_zone* trip_point_1_hyst 0660 system system
/dev/dmabuf_imx 0664 system system
/sys/class/backlight/* brightness 0660 system system
/dev/ttymxc1 0666 nfc nfc
/dev/ttymxc2 0666 nfc nfc
/dev/nxpnfc 0666 nfc nfc
# for libcamera
/dev/media* 0660 system camera
/dev/v4l-subdev* 0660 system camera
5. Apply the NXP AOSP patches
As the official NXP NFC patches is only for AOSP android-15.0.0_r1, and there are big different between android-15.0.0_r1 and android-15.0.0_r32. So, before apply the patches, I copy the nfc folders from android-15.0.0_r1 to replace the nfc folders in android-15.0.0_r32.
First, download the AOSP android-15.0.0_r1 from github.
$ mkdir android-15.0.0_r1
$ cd android-15.0.0_r1
$ repo init -u https://android.googlesource.com/platform/manifest -b android-15.0.0_r1
$ repo sync
Then, remove the following folders from android-15.0.0_r32. And then copy the following nfc folders from android-15.0.0_r1 to replace the same folders in android-15.0.0_r32.
packages/apps/Nfc
frameworks/base/nfc
frameworks/base/nfc-extras
system/nfc
for example:
$ rm -rf android_build/packages/apps/Nfc
$ cp -ra android-15.0.0_r1/packages/apps/Nfc android_build/packages/apps/
I write a script to download the patches from the github. Customer could put the following scripts on the same directory with android_build.
AOSP_adaptation.sh
# nxp_nci_hal_nfc
git clone "https://github.com/nxp-nfc-infra/nxp_nci_hal_nfc.git"
cd nxp_nci_hal_nfc
git checkout br_ar_15_comm_infra_dev
cp -rf * ../android_build/packages/apps/Nfc/
cd ..
# nxp_nci_hal_libnfc-nci
git clone "https://github.com/nxp-nfc-infra/nxp_nci_hal_libnfc-nci.git"
cd nxp_nci_hal_libnfc-nci
git checkout br_ar_15_comm_infra_dev
cp -rf * ../android_build/system/nfc/
cd ..
# nfcandroid_nfc_hidlimpl
git clone "https://github.com/nxp-nfc-infra/nfcandroid_nfc_hidlimpl.git"
cd nfcandroid_nfc_hidlimpl
git checkout br_ar_15_comm_infra_dev
cp -rf * ../android_build/hardware/nxp/nfc
cd ..
# nfcandroid_frameworks
git clone "https://github.com/nxp-nfc-infra/nfcandroid_frameworks.git"
cd nfcandroid_frameworks
git checkout br_ar_15_comm_infra_dev
mkdir ../android_build/vendor/nxp/frameworks
cp -rf * ../android_build/vendor/nxp/frameworks
cd ..
# nfcandroid_emvco_aidlimpl
git clone "https://github.com/nxp-nfc-infra/nfcandroid_emvco_aidlimpl.git"
cd nfcandroid_emvco_aidlimpl
git checkout br_ar_15_comm_infra_dev
mkdir ../android_build/hardware/nxp/emvco
cp -rf * ../android_build/hardware/nxp/emvco
cd ..
# nfcandroid_platform_reference
git clone "https://github.com/nxp-nfc-infra/nfcandroid_platform_reference.git"
cd nfcandroid_platform_reference
git checkout br_ar_15_comm_infra_dev
cp -rf vendor/nxp/* ../android_build/vendor/nxp/
cd ..
# nfcandroid_infra_test_apps
git clone https://github.com/nxp-nfc-infra/nfcandroid_infra_test_apps.git
cd nfcandroid_infra_test_apps/
git checkout br_ar_15_comm_infra_dev
cd test_apps/
cp -rf SMCU_Switch/ ../../android_build/packages/apps/
cp -rf EMVCoModeSwitchApp/ ../../android_build/packages/apps/Nfc/
cp -rf load_unload/ ../../android_build/hardware/nxp/nfc/
cp -rf SelfTestAidl/ ../../android_build/hardware/nxp/nfc/
cd ../..
# nfcandroid_infra_comm_libs
git clone "https://github.com/nxp-nfc-infra/nfcandroid_infra_comm_libs.git"
cd nfcandroid_infra_comm_libs
git checkout br_ar_15_comm_infra_dev
cp -rf nfc_tda/ ../android_build/system/
cp -rf emvco_tda/ emvco_tda_test/ ../android_build/hardware/nxp/emvco/
cp -rf NfcTdaTestApp/ ../android_build/packages/apps/Nfc/
cd ..
Apply_patches.sh
cd android_build/build/bazel/
patch -p1 < ../../../nfcandroid_platform_reference/build_cfg/build_pf_patches/AROOT_build_bazel.patch
cd ../release
patch -p1 < ../../../nfcandroid_platform_reference/build_cfg/build_pf_patches/AROOT_build_release.patch
cd ../../external/libchrome
patch -p1 < ../../../nfcandroid_platform_reference/build_cfg/build_pf_patches/AROOT_external_libchrome.patch
cd ../../frameworks/base
patch -p1 < ../../../nfcandroid_platform_reference/build_cfg/build_pf_patches/AROOT_frameworks_base.patch
cd ../../system/logging
patch -p1 < ../../../nfcandroid_platform_reference/build_cfg/build_pf_patches/AROOT_system_logging.patch
So, run the AOSP_adaptation.sh first, then run the Apply_patches.sh.
6. Put changes into hardwatre/interfaces/compatibility_matrices
Different compatibility matrix for different Android versions.
File: android_build/hardware/interfaces/compatibility_matrices/compatibility_matrix.202404.xml
<hal format="aidl">
<name>android.hardware.audio.effect</name>
<version>1-2</version>
<interface>
<name>IFactory</name>
<instance>default</instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>nxp.hardware.imx_dek_extractor</name>
+ <version>1</version>
+ <interface>
+ <name>IDek_Extractor</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>vendor.nxp.nxpnfc</name>
+ <version>2.0</version>
+ <interface>
+ <name>INxpNfc</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
+ <name>vendor.nxp.emvco</name>
+ <version>1</version>
+ <interface>
+ <name>INxpEmvco</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
<hal format="aidl">
<name>android.hardware.audio.sounddose</name>
<version>1-3</version>
7. Change the device specific .mk
For pn7160, NXP_NFC_HW should equal to pn7160.
For pn7220, NXP_NFC_HW should equal to pn7220_i2cs.
File : android_build/vendor/nxp/nfc/device-nfc.mk
#####
##### NXP NFC Device Configuration makefile
######
NXP_NFC_HOST := $(TARGET_PRODUCT)
ifndef TARGET_NXP_NFC_HW
NXP_NFC_HW := pn7160
else
NXP_NFC_HW := $(TARGET_NXP_NFC_HW)
endif
NXP_NFC_PLATFORM := pn54x
NXP_VENDOR_DIR := nxp
NXP_I2CM_S := $(TARGET_NXP_I2C_M_S)
File: android_build/vendor/nxp/emvco/device-emvco.mk
NXP_VENDOR_DIR := nxp
NXP_NFC_HW := $(TARGET_NXP_NFC_HW)
ifeq ($(strip $(TARGET_NXP_NFC_HW)),)
NXP_NFC_HW := pn7160
endif
# Nfc service has dependency with EMVCo JAR
PRODUCT_PACKAGES += \
com.nxp.emvco
8. Now, you can start to build the Android BSP
For i.MX8MN EVK,
$ source build/envsetup.sh
$ lunch evk_8mn-nxp_stable-userdebug
$ export TARGET_RELEASE=nxp_stable
$ build_build_var_cache
$ ./imx-make.sh -j4 2>&1 | tee build-log.txt
When building the BSP, there will have many errors during the build. I list some errors and the reference solution below for customer reference.
Error
Reference Solution
Complain about the nfc_aconifg_flags.
packages/apps/Nfc/flags/Android.bp
aconfig_declarations {
// name: "nfc_aconfig_flags",
name: "com.android.nfc.flags-aconfig",
package: "com.android.nfc.flags",
container: "system",
srcs: ["nfc_flags.aconfig"],
}
java_aconfig_library {
// name: "nfc_aconfig_flags_lib",
// aconfig_declarations: "nfc_aconfig_flags",
name: "com.android.nfc.flags-aconfig-java",
aconfig_declarations: "com.android.nfc.flags-aconfig",
min_sdk_version: "33",
apex_available: [
"//apex_available:platform",
"com.android.nfcservices",
],
}
java_library {
name: "nfc_flags_lib",
sdk_version: "system_current",
min_sdk_version: "33",
srcs: [
"lib/**/*.java",
],
static_libs: [
"com.android.nfc.flags-aconfig-java",
],
Complain about the android.hardware.nfc-V2-ndk
File: hardware/interfaces/nfc/aidl/vts/functional/Android.bp
Change android.hardware.nfc-V2-ndk to vendor.nxp.nxpnfc_aidl-V2-ndk
platform_testing/build/tasks/tests/native_test_list.mk: error: continuous_native_tests: Unknown installed file for module 'libnfc-nci-jni-tests'
remove 'libnfc-nci-jni-tests' in
native_test_list.mk
error: packages/apps/Nfc/tests/instrumentation/Android.bp:6:1: module "NfcNciInstrumentationTests" variant "android_common": cannot depend directly on java_sdk_library "android.test.runner"; try depending on "android.test.runner.stubs", "android.test.runner.stubs.system", "android.test.runner.stubs.test", or "android.test.runner.impl" instead
The hints are gave in the error message..
Change the "android.test.runner" to "android.test.runner.stubs", "android.test.runner.stubs.system", "android.test.runner.stubs.test", or "android.test.runner.impl".
error: vendor/nxp/frameworks/nfc/Android.bp:12:1: module "com.nxp.nfc" variant "android_common": depends on //frameworks/base/nfc:framework-nfc.impl which is not visible to this module
You may need to add "//vendor/nxp/frameworks/nfc" to its visibility
File : frameworks/base/nfc/Android.bp
permitted_packages: [
"android.nfc",
"com.android.nfc",
],
impl_library_visibility: [
"//frameworks/base:__subpackages__",
"//cts/hostsidetests/multidevices/nfc:__subpackages__",
"//cts/tests/tests/nfc",
"//vendor:__subpackages__",
"//packages/apps/Nfc:__subpackages__",
],
packages/apps/Nfc/nci/src/com/android/nfc/dhimpl/NativeT4tNfceeManager.java:20: error: duplicate class: com.android.nfc.dhimpl.NativeT4tNfceeManager
Edit the file
packages/apps/Nfc/nci/src/com/android/nfc/dhimpl/NativeT4tNfceeManager.java
then comment out the duplicated class.
android/R.java:12483: error: could not resolve field FLAG_NFC_ASSOCIATED_ROLE_SERVICES
@android.annotation.FlaggedApi(android.nfc.Flags.FLAG_NFC_ASSOCIATED_ROLE_SERVICES)
Edit
frameworks/base/nfc/java/android/nfc/flags.aconfig
Add the below flag.
flag {
name: "nfc_associated_role_services"
is_exported: true
namespace: "nfc"
description: "Share wallet role routing priority with associated services"
bug: "366243361"
}
FAILED:
platform_testing/build/tasks/tests/native_test_list.mk: error: continuous_native_tests: Unknown installed file for module 'libnfc-nci-tests'
Remove the libnfc-nci-tests in native_test_list.mk.
prebuilts/clang/host/linux-x86/clang-r536225/include/c++/v1/string:780:43: error: implicit instantiation of undefined template 'std::char_traits<unsigned char>'
780 | static_assert((is_same<_CharT, typename traits_type::char_type>::value),
| ^
packages/apps/Nfc/nci/jni/NativeNfcTda.cpp:32:35: note: in instantiation of template class 'std::basic_string<unsigned char>' requested here
32 | static std::basic_string<uint8_t> sRxTdaDataBuff;
| ^
Edit the packages/apps/Nfc/nci/jni/NativeNfcTda.cpp using android::base::StringPrintf;
extern bool nfc_debug_enabled;
SyncEvent sCtLibSyncEvt;
//static std::basic_string<uint8_t> sRxTdaDataBuff;
static std::basic_string<char> sRxTdaDataBuff;
packages/apps/Nfc/nci/jni/NativeT4tNfcee.cpp:493:21: error: no matching member function for call to 'append'
493 | sRxDataBuffer.append(data.p_data, data.len);
| ~~~~~~~~~~~~~~^~~~~~
Edit the packages/apps/Nfc/nci/jni/NativeT4tNfcee.cpp void NativeT4tNfcee::t4tReadComplete(tNFA_STATUS status, tNFA_RX_DATA data) {
mT4tOpStatus = status;
if (status == NFA_STATUS_OK) {
if (data.len > 0) {
sRxDataBuffer.insert(sRxDataBuffer.end(), data.p_data,
data.p_data + data.len);
LOG(DEBUG) << StringPrintf("%s: Read Data len new: %d ", __func__,
data.len);
}
}
SyncEventGuard g(mT4tNfcEeRWCEvent);
mT4tNfcEeRWCEvent.notifyOne();
}
frameworks/base/core/java/android/provider/Settings.java:2351: error: could not resolve field FLAG_NFC_ACTION_MANAGE_SERVICES_SETTINGS
@FlaggedApi(android.nfc.Flags.FLAG_NFC_ACTION_MANAGE_SERVICES_SETTINGS)
File: frameworks/base/nfc/java/android/nfc/flags.aconfig
Add the following to the flags.aconfig
flag {
name: "nfc_action_manage_services_settings"
is_exported: true
namespace: "nfc"
description: "Add Settings.ACTION_MANAGE_OTHER_NFC_SERVICES_SETTINGS"
bug: "358129872"
}
There are some errors are not listed in the table because there will have some hints to correct the error in the error message. Customer could follow the hints and base on the needs to modify the source code.
Sometime, customer could compare the source code between r1 and r32. Here is the AOSP source code android-15.0.0_r32 and the android-15.0.0_r1.
9. Download the image to the i.MX8MN EVK board
- Switch to download mode on the 8MN EVK board
- Download the Android 15 BSP i.MX8MN EVK demo image from the Android BSP web page first. Because there are UUU script and necessary image files already in the demo image package.
- Download the UUU from here : Releases · nxp-imx/mfgtools
- Put the UUU executable file into the demo image folder. uuu_imx_android_flash.bat is the script also in the same folder.
- After your building is succeed, Copy the images to the demo image folder. The images are located in android_build/out/target/product/evk_8mn/
- Run the UUU script to download the images to the EVK board.
Reference:
i.MX6ULL EVK running Yocto Linux + PN7160
Porting PN7160 to Android 14 on i.MX8M Nano board
Android OS for i.MX Applications Processors | NXP Semiconductors
PN7160/PN7220 – Android 15 porting guide
Plug-n-Play NFC Frontend with Integrated Firmware | NXP Semiconductors
View full article