Android HAL in-depth exploration (5): Debugging HAL errors and solutions

When we learn Android HAL development, we may encounter some compilation or runtime errors, which may affect the exploration script. In order to effectively locate and resolve these errors, you need to understand the architecture, tools, and methods of Android HAL. This article will introduce some of my own debugging skills and solutions to common errors when learning Android HAL. I hope it can help everyone.

Other articles on the Internet will never tell you the complete debugging process. At most, they will only tell you the results. You will know how many pitfalls there are when you try it yourself. This article only records less than half of the problems I encountered. Some of them are not very common and I am too lazy to record them.

Please correct me if there are any errors. HAL-related debugging and solutions will be updated here later. If you have any questions, please feel free to ask~

Series of articles:
Android HAL in-depth exploration (1): Architecture overview
Android HAL in-depth exploration (2): Traditional HAL and file encryption and decryption simulation
Android HAL in-depth exploration (3): HIDL Passthrough mode and serial port data callback simulation
Android HAL in-depth exploration (4 ): HIDL Binderized mode and CAN data callback simulation
Android HAL in-depth exploration (5): Debugging HAL error reports and solutions

问题1:declares types rather than the expected interface type ‘ICanBus’

When trying to compile a [email protected]HAL called, you may encounter the following error:

declares types rather than the expected interface type 'ICanBus'
ERROR: Could not parse [email protected]::ICanBus. Aborting.

.halThis error means that the interface is not defined correctly in our file, but some types (like or ) ICanBusare declared instead . This violates the syntax rules of the HIDL language, since the file must start with an interface definition, and there can only be one interface definition.structenum.hal

简单的说就是hal文件里面必须以interface 开头,不然就会报这个错误。

Reason: .halThe structure of the file does not comply with HIDL syntax rules

HIDL language is a language used to define Android HAL interfaces. It has some specific syntax rules and conventions. One of them is that .halthe file must start with an interface definition, and there can only be one interface definition. For example, if you want to define an [email protected]::ICanBusinterface named, .halthe file should look like this:

package [email protected];

interface ICanBus {
    // methods and types for the interface
}

structIf some types (such as or ) are declared before or after the interface definition enum, then the HIDL compiler ( hidl-gen) will report an error because it cannot parse our interface definition. If our .halfile looked like this:

package [email protected];

struct CanFrame {
    // fields for the struct
}

interface ICanBus {
    // methods and types for the interface
}

Then the HIDL compiler will report an error:

declares types rather than the expected interface type 'ICanBus'
ERROR: Could not parse [email protected]::ICanBus. Aborting.

Solution: Reorganize .halfiles or create new .halfiles

In order to solve this error, there are two solutions:

  • Reorganize .halthe file: Move the interface definition to the top of the file, and then place the other type definitions. The above .halfile can be modified to:
package [email protected];

interface ICanBus {
    // methods and types for the interface
}

struct CanFrame {
    // fields for the struct
}
  • Create a new .halfile: If we want to separate the type definition and the interface definition, we can create a new .halfile to store the type definition and .halimport it in the original file. You can create a CanTypes.halfile named:
package [email protected];

struct CanFrame {
    // fields for the struct
}

.halThen import it in the original file:

package [email protected];

import [email protected];

interface ICanBus {
    // methods and types for the interface
}

问题2:Expecting only package name and version

When trying to use hidl-gentools to generate implementation code for a HIDL interface, you may encounter the following error:

ERROR: Expecting only package name and version.
ERROR: output handler failed.

This error means that our command line parameters did not meet hidl-genthe requirements because we provided redundant or wrong parameters.

Reason: The command line parameter format is incorrect.

hidl-genIt is a tool for generating implementation code of HIDL interfaces. It has some specific command line parameter formats and options. One of the required parameters is the package name and version number of the HIDL interface, which should look like this:

package@version

For example, if we want to generate [email protected]::ICanBusthe implementation code of the interface, we should provide the following parameters:

[email protected]

If other content is added after this parameter, such as the interface name or file name, an hidl-generror will be reported because it only expects a package name and version number.

Solution: Correct the command line parameters

In order to solve this error, we need to modify our command line parameters to only provide the package name and version number. For example, if we used this command before:

hidl-gen -o hardware/interfaces/can_bus/1.0/default -Landroidbp-impl \
-randroid.hardware:hardware/interfaces \
-randroid.hidl:system/libhidl/transport \
[email protected]::ICanBus

It should be modified to:

hidl-gen -o hardware/interfaces/can_bus/1.0/default -Landroidbp-impl \
-randroid.hardware:hardware/interfaces \
-randroid.hidl:system/libhidl/transport \
[email protected]
hidl-gen -o hardware/interfaces/can_bus/1.0/default -Lc++-impl \
-randroid.hardware:hardware/interfaces \
-randroid.hidl:system/libhidl/transport \
[email protected]::ICanBus
这个命令会在输出目default录中生成C++或Android BP的接口代码


hidl-gen -o hardware/interfaces/can_bus/1.0/default -Landroidbp-impl \
-randroid.hardware:hardware/interfaces \
-randroid.hidl:system/libhidl/transport \
[email protected]
这个命令会在输出default目录中生成一个名为Android.bp的文件,包含了HIDL软件包的编译信息。

hardware/interfaces/can_bus$ tree
.
└── 1.0
    ├── Android.bp
    ├── default
    │   ├── Android.bp
    │   ├── CanBus.cpp
    │   └── CanBus.h
    └── ICanBus.hal

问题3:module “[email protected]” variant “android_arm64_armv8-a_cortex-a55”: depends on //system/libhwbinder:libhwbinder which is not visible to this module

When trying to compile a [email protected]HAL service called, you may encounter the following error:

error: hardware/interfaces/can_bus/1.0/service/Android.bp:1:1: module "[email protected]" variant "android_arm64_armv8-a_cortex-a55": depends on //system/libhwbinder:libhwbinder which is not visible to this module
10:08:10 soong bootstrap failed with: exit status 1

This error means that our HAL service module depends on a library that is not visible to it, ie //system/libhwbinder:libhwbinder. This violates the visibility rules of the Soong build system, as each module must declare other modules it can access.

Cause: Visibility attribute missing or wrong

The Soong build system, Android's tool for compiling source code, uses a language called Blueprint to describe modules and the relationships between them. The Blueprint language has some properties and keywords to control the visibility of modules, that is, which modules can access which modules.

One of the properties is visibilitythat it is possible to specify in a module's definition which other modules can depend on it. If you want to make a testhalmodule named visible only to other modules in the same package, you can write:

cc_library {
    name: "testhal",
    visibility: [":__subpackages__"],
}

If you want to make a testhal2module named visible to all other modules, you can write:

cc_library {
    name: "testhal2",
    visibility: ["//visibility:public"],
}

In the above example, //it represents the root directory, :represents the separator within the package, and __subpackages__represents all sub-packages in the same package.

If a module does not specify visibilityan attribute, then by default it is only visible to other modules in the same package. If a module specifies incorrect or mismatching visibilityattributes, it may cause compilation errors.

In my case, the HAL service module relied on a library located in the system partition, ie //system/libhwbinder:libhwbinder. But visibilitythe properties of this library are like this:

cc_library {
    name: "libhwbinder",
    visibility: [":__subpackages__"],
}

This library is only visible to other modules in the same package, that is, it is only visible to modules located under //hardware/interfaces/can_bus/1.0/...(I guess it is impossible to express ). //system/libhwbinder/...And my HAL service module is located //hardware/interfaces/can_bus/1.0/service/...below, so it cannot access this library.

Solution: Modify or add visibility properties

To resolve this error, I tried two options:

  • Modify the visibility properties of libraries: Modify libraries in the system partition and modify their visibility properties to make them visible to required modules. If you want to make it //hardware/interfaces/can_bus/1.0/service/...visible to all HAL service modules, you can modify it like this:
cc_library {
    name: "libhwbinder",
    export_include_dirs: ["include"],
    visibility: [
        ":__subpackages__",
        "//hardware/interfaces/...:service",
    ],
}

This way you //hardware/interfaces/can_bus/1.0/...can servicedepend on this library in any included module below.
or

+++ b/system/libhwbinder/Android.bp
@@ -66,7 +66,11 @@ cc_library {
    
    
 
     export_include_dirs: ["include"],
 
-    visibility: [":__subpackages__"],
+//    visibility: [
+//    ":__subpackages__",
+//    ],
+visibility: ["//visibility:public"],
+
 }

In this way, all modules and all paths can depend on this library.


Question 4: VNDK library list has been changed

When I try to compile a [email protected]HAL called, I get the following error:

[ 10% 571/5241] build out/target/product/rk3568_r/obj/PACKAGING/vndk_intermediates/check-list-timestamp
FAILED: out/target/product/rk3568_r/obj/PACKAGING/vndk_intermediates/check-list-timestamp
/bin/bash -c "(( diff --old-line-format=\"Removed %L\"    --new-line-format=\"Added %L\"          --unchanged-line-format=\"\"    build/make/target/product/gsi/30.txt out/soong/vndk/vndk.libraries.txt         || ( echo -e \" error: VNDK library list has been changed.\\n\" \"       Changing the VNDK library list is not allowed in API locked branches.\"; exit 1 )) ) && (mkdir -p out/target/product/rk3568_r/obj/PACKAGING/vndk_intermediates/ ) && (touch out/target/product/rk3568_r/obj/PACKAGING/vndk_intermediates/check-list-timestamp )"
Added VNDK-core: [email protected]
 error: VNDK library list has been changed.
        Changing the VNDK library list is not allowed in API locked branches.
10:21:14 ninja failed with: exit status 1

This error means that my HAL was added to the VNDK library list, but current.txtwas not listed in the file, causing a compilation error. current.txtThe file is a file that defines the list of VNDK libraries supported by the current Android version. It is located build/make/target/product/vndk/in the directory. 30.txtThe file is a file that defines the list of VNDK libraries supported by Android 11. It is located build/make/target/product/gsi/in the directory.

Reason: The VNDK library list is inconsistent or illegal

According to the information I checked:

The VNDK library list is a mechanism used to ensure the stability of the interface between vendors and systems. It specifies which framework shared libraries can be used by vendor modules and maintains compatibility between different Android versions. The VNDK library list has the following characteristics:

  • The list of VNDK libraries is in alphabetical order.
  • The VNDK library list only includes eligible VNDK libraries (Eligible-VNDK) and VNDK-core libraries.
  • The VNDK library list does not include the LL-NDK library, VNDK-SP library, VNDK-SP-Ext library, VNDK-Ext library, FWK-ONLY library and SP-HAL library.
  • VNDK library list is not allowed to change in API locked branches.

API locked branches refer to Android version branches that have been released or are about to be released, such as android-11 or android-s-beta-2. In these branches, the VNDK library list has been frozen, and no more libraries can be added or removed. This is to ensure compatibility between system and vendor partitions, as well as to support framework-specific updates (i.e. only update the system partition and not the vendor partition).

If we try to modify the VNDK library list in the API locked branch, or add libraries that do not comply with VNDK standards to the VNDK library list, the compilation system will report an error and stop the build.

Solution: Decide whether to add it to VNDK based on the nature and purpose of HAL

To resolve this error, I need to decide based on the nature and purpose of my HAL whether it should be added to the VNDK or not. If my HAL does need to be part of the VNDK, I can follow these steps:

  1. Updatecurrent.txt : In the file, will be added to the appropriate location current.txtdepending on the nature of my HAL . [email protected]If it is a core VNDK library, you can add it to VNDK-corethe section. You must pay attention to inserting them in alphabetical order, otherwise a compilation error will be reported.

  2. Update30.txt : 30.txtHere is the list of VNDK libraries for Android 11. If modified , the same modifications current.txtshould be made in to ensure consistency between the two. 30.txtCare must be taken to insert them in alphabetical order.

But if our HAL is not supposed to be part of the VNDK, then any section marking it as VNDK should be removed from the build configuration and make sure it is not added to the VNDK library list. You can add an attribute to the Android.bp file of the HAL module (I haven’t figured out what the specific difference is yet, but I read this on the Internet):

vndk: {
    enabled: false,
},

This way the system will not see the module as a VNDK library, but as a normal HAL module. This module will not be shared by the system partition and the supplier partition, but can only be used by the supplier partition.

This problem bothered me for a long time when I first worked on HIDL. Fortunately, I had added notes based on my review before. . .
In short, I will tell you a very simple method. After comparing these two files with a comparison tool, directly use the one in the out directory to the build directory and it will be OK out\soong\vndk\vndk.libraries.txt.
build\target\product\gsi\30.txt
Insert image description here

For more VNDK, please refer to the following link:


Question 5: hwservicemanager cannot find the HAL interface error

09-09 15:24:22.448  8915  8915 I [email protected]: CanBusService created
09-09 15:24:22.449   141   141 I hwservicemanager: getTransport: Cannot find entry [email protected]::ICanBus/default in either framework or device manifest.
09-09 15:24:22.450  8915  8915 E HidlServiceManagement: Service [email protected]::ICanBus/default must be in VINTF manifest in order to register/get.

This error means that my HAL service is trying to register to hwservicemanager, but hwservicemanagerthe corresponding entry cannot be found in the VINTF (Vendor Interface) manifest. VINTF manifests were introduced in Android 8.0 and higher to describe the interface between the HAL and the framework.

In order to resolve this error, we need to ensure that our HAL interface has been added to the VINTF manifest. Here are the steps on how to do this:

Step 1: Create or modify a VINTF manifest

In the source code directory, usually systemunder the directory, find a manifest.xmlfile called . This file is used to describe the HAL interface and version provided by our device, as well as other device-related information, such as SELinux policy version, etc.

Step 2: Add HAL interface to manifest

In manifest.xml, add our HAL interface. The name, transmission method, version and instance of the interface need to be specified. For example, if we want to add an [email protected]::ICanBusinterface named and it uses hwbinder as the transport and has an instance named default, we can write:

<manifest version="1.0" type="device">
。。。
    <hal format="hidl">
        <name>android.hardware.can_bus</name>
        <transport>hwbinder</transport>
        <version>1.0</version>
        <interface>
            <name>ICanBus</name>
            <instance>default</instance>
        </interface>
    </hal>
    <!-- 其他HAL接口 -->
。。。
</manifest>

<hal>Multiple versions and instances can be added in a tag, as well as HAL interfaces in other formats, such as AIDL or native.

For more information about hwservicemanager and VINTF manifest, you can refer to the following link:

  • HIDL : Introduces the HIDL language and architecture, and how to use hwservicemanager to manage HIDL services.
  • Vendor Interface Object : Introduces the design and role of VINTF objects, and how to use lists and matrices to describe and match HAL interfaces.

Issue 6: Debugging and resolving errors where the extends attribute references a non-VNDK library

error: hardware/interfaces/can_bus/1.0/service/Android.bp:2:1: module "[email protected]" variant "android_vendor.30_arm64_armv8-a_cortex-a55": `extends` refers a non-vndk module "libhidltransport"
14:34:14 soong bootstrap failed with: exit status 1

This error prompts me that the system? A non-VNDK library is referenced in the partition, that is libhidltransport. In Android 8.0 and above, to ensure device backward compatibility, Google introduced the VNDK concept. VNDK libraries are those libraries that are safe to use in vendor partitions.

To solve this problem, here is my attempt:

Method 1: Remove the extends attribute

If an inherited libhidltransportproperty is not needed, you can simply vndkremove extendsthe property from the block. For example, in the Android.bp file of the HAL module, you can write:

cc_binary {
    name: "[email protected]",
    vendor: true,
    vndk: {
        enabled: true,
        support_system_process: false,
    },
    srcs: ["CanBus.cpp"],
    shared_libs: [
        "[email protected]",
        "libhidltransport",
        "libhidlbase",
        "libutils",
        "libcutils",
        "liblog",
    ],
}

This way the properties of non-VNDK libraries will not be referenced, but the default properties will be used.

Method 2: Use the VNDK version of the library

If libhidltransportthere is a VNDK version, for example libhidltransport_vndk, we should shared_libsuse it in and extendsspecify it in . In the Android.bp file of our HAL module, we can write:

cc_binary {
    name: "[email protected]",
    vendor: true,
    vndk: {
        enabled: true,
        support_system_process: false,
        extends: "libhidltransport_vndk",
    },
    srcs: ["CanBus.cpp"],
    shared_libs: [
        "[email protected]",
        "libhidltransport_vndk",
        "libhidlbase",
        "libutils",
        "libcutils",
        "liblog",
    ],
}

You can inherit the properties of the VNDK library and will not reference non-VNDK libraries.

There is another way, which is similar to question 3. In fact, libhidltransport also has a visible attribute, which needs to be searched in the source code. Anyway, I was a little dizzy after working on Android.bp for a long time, so I just killed the libhidltransport dependent library. , it has no effect and I don’t understand the reason. Just treat this as a hole and fill it in later.

Question 7: How to debug and solve the error that the init process cannot start the service

09-09 15:50:30.479     0     0 E init    : Control message: Could not ctl.start for 'vendor.hw_canbus' from pid: 2563 (start vendor.hw_canbus): File /system/bin/hw/[email protected](labeled "u:object_r:system_file:s0") has incorrect label or no domain transition from u:r:init:s0 to another SELinux domain defined. Have you configured your service correctly? https://source.android.com/security/selinux/device-policy#label_new_services_and_address_denials
09-09 15:50:30.357  2563  2563 W libc    : Unable to set property "ctl.start" to "vendor.hw_canbus": error code: 0x20

This error means that the HAL service cannot initbe started by the process because it does not have the correct SELinux context or domain translation. initThe process is the core process in the Android system responsible for starting and managing services. It has its own SELinux context (usually u:r:init:s0) and needs to follow SELinux policies to perform the starting and stopping of services.

In order to resolve this error, you need to ensure the following:

Step 1: Confirm file context

File context is a mechanism used by SELinux to mark the security attributes of files, which includes user, role, type and optional level. File context can ls -Zbe viewed with commands, for example:

$ ls -Z /system/bin/hw/[email protected]
-rwxr-xr-x root root u:object_r:system_file:s0 /system/bin/hw/[email protected]

Here you can see that the file type system_fileis a general type and is not suitable for use in our HAL service. We need to define a specialized type for the HAL service, for example can_bus_exec, and set the file context to that type at compile time.

Step 2: Service Definition

Service definition is .rca mechanism for specifying the start and stop methods, dependencies, priorities, resource limits and other information of the HAL service in a file. .rcFiles are usually located in our device-specific source code directory, eg system/etc/init/[email protected]. In .rcthe file, we need to add a tag similar to the following for our HAL service:

service vendor.hw_canbus /system/bin/hw/[email protected]
    class hal
    user system
    group system
    seclabel u:object_r:hal_canbus_default_exec:s0


You can also add the following lines in the file_contexts file:

/(vendor|system)/bin/hw/android\.hardware\.canbus@1\.0-service   u:object_r:hal_canbus_default_exec:s0

This paragraph indicates that a service named is defined vendor.hw_canbus, which executes a /system/bin/hw/[email protected]program named. It belongs to mainthe category, runs as system user and system group, and has a seclabel u:object_r:hal_canbus_default_exec:s0SELinux context named. It is a one-time service, that is, it only runs once and does not restart.

Step 3: Recompile and confirm

After completing the changes, run the following command on the device to check whether our HAL service has been started correctly
. If everything is OK, you can see output similar to the following:

09-11 09:07:46.421  9125  9125 I [email protected]: CanBusService created
09-11 09:07:46.424  9125  9125 I HidlServiceManagement: Registered [email protected]::ICanBus/default
09-11 09:07:46.424  9125  9125 I HidlServiceManagement: Removing namespace from process name [email protected] to [email protected].
09-11 09:07:46.424  9125  9125 I [email protected]: CanBusService is ready.
rk
#输出结果显示了一个名为[email protected]的进程,其进程ID为3435,它是由root用户启动的,并且当前处于睡眠状态(S)
3568_r:/ # ps -A | grep can
root           3435    567 10773968  2788 binder_thread_read  0 S [email protected]
#输出结果显示了一个名为[email protected]::ICanBus/default的HAL服务。这表示系统上有一个实现了[email protected]接口的HAL服务,并且它的实例名为default。
rk3568_r:/ # lshal | grep can
FM    N [email protected]::ICanBus/default                             0/1        3435   148

Label debugging process

rk3568_r:/system # find -name "*can*.rc"
./etc/init/[email protected]
rk3568_r:/system # cat ./etc/init/[email protected]
on boot
    start vendor.hw_canbus

service vendor.hw_canbus /system/bin/hw/[email protected]
    class hal
    user system
    group system
    seclabel u:object_r:hal_canbus_default_exec:s0
rk3568_r:/system # start vendor.hw_canbus
Unable to start service 'vendor.hw_canbus'
See dmesg for error reason.

rk3568_r:/ # ls -llZ  /system/bin/hw/[email protected]
-rwxr-xr-x 1 root shell u:object_r:system_file:s0  16616 2023-09-09 15:06:27.000000000 +0800 /system/bin/hw/[email protected]
rk3568_r:/ # restorecon /system/bin/hw/[email protected]
SELinux: Loaded file_contexts
rk3568_r:/ # ls -llZ  /system/bin/hw/[email protected]
-rwxr-xr-x 1 root shell u:object_r:system_file:s0  16616 2023-09-09 15:06:27.000000000 +0800 /system/bin/hw/[email protected]


rk3568_r:/ # chcon u:object_r:hal_canbus_default_exec:s0 /system/bin/hw/[email protected]
r:hal_canbus_default_exec:s0 /system/bin/hw/[email protected]^C                                     <
130|rk3568_r:/ # ls -llZ  /system/bin/hw/[email protected]
-rwxr-xr-x 1 root shell u:object_r:hal_canbus_default_exec:s0  16616 2023-09-09 15:06:27.000000000 +0800 /system/bin/hw/[email protected]

This indicates that our HAL service has started successfully and has the correct SELinux context.

Question 8: Prompt android/hardware/can_bus/1.0/ICanBus.hfile cannot be found

When I added native frameworks/base/services/core/jni/com_android_server_SystemCanBusService.cpp, I encountered an error when compiling, indicating that android/hardware/can_bus/1.0/ICanBus.hthe file could not be found.

frameworks/base/services/core/jni/com_android_server_SystemCanBusService.cpp:6:10: fatal error: 'android/hardware/can_bus/1.0/ICanBus.h' file not found
#include <android/hardware/can_bus/1.0/ICanBus.h>
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

Reason: Not generated correctly

android/hardware/can_bus/1.0/ICanBus.hThe header file was not generated correctly or its path was not correctly included in the compile-time header file search path.

Solution: Modify jni Android.bp so that the library is correctly included in the compilation dependencies

  1. Use hidl-genthe command to manually generate the required header files. This command will hardware/interfaces/can_bus/1.0/defaultgenerate a gensubdirectory under the directory containing android/hardware/can_bus/1.0/ICanBus.hthe files.
  hidl-gen -o hardware/interfaces/can_bus/1.0/default -Lc++-headers \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport \
  [email protected]
hardware$ find -name "ICanBus.h"
./interfaces/can_bus/1.0/default/android/hardware/can_bus/1.0/ICanBus.h
  1. Modify frameworks/base/services/core/jni/Android.bpthe file to ensure that [email protected]the library is correctly included in the build dependencies.

    @@ -155,6 +156,7 @@ cc_defaults {
            "[email protected]",
            "[email protected]",
            "[email protected]",
    +        "[email protected]",
            "[email protected]",
            "[email protected]",
            "[email protected]",
    

The above steps can solve ICanBus.hthe problem of file not being found during compilation.

Guess you like

Origin blog.csdn.net/SHH_1064994894/article/details/132779671