背景
项目中需要在Android 11中自定义HAL,由于从Android 11开始,可以使用AIDL定义HAL,本文简单记录了AIDL的HAL创建方法。
- 注意:本文适用于Android 11,其他版本可能有不同的问题需要不同的解决方案。
步骤
1. 设置编译环境
source build/envsetup.sh
lunch aosp_trout_arm64-userdebug
2. 创建HAL目录
创建如下目录:
/hardware/interfaces/automotive/helloworld
- 注意:后续所有目录均为上面目录下的相对路径。
3. 创建AIDL
- 添加AIDL文件
aidl/android/hardware/automotive/helloworld/IHelloworld.aidl:
package android.hardware.automotive.helloworld;
@VintfStability
interface IHelloworld {
void sayHello(in String name);
}
- 添加 Android.bp
aidl/Android.bp:
aidl_interface {
name: "android.hardware.automotive.helloworld",
vendor_available: true,
srcs: [
"android/hardware/automotive/helloworld/*.aidl",
],
stability: "vintf",
owner: "mycompany",
backend: {
java: {
platform_apis: true,
}
},
versions: [],
}
- 注意: 将owner设置为组织名称。
Android.bp:
package {
default_applicable_licenses: ["Android-Apache-2.0"],
}
cc_defaults {
name: "HelloworldiHalInterfaceDefaults",
static_libs: [
"android.hardware.automotive.helloworld-ndk_platform",
],
}
4. 生成 aidl_api
mm android.hardware.automotive.helloworld-update-api
此命令会生成如下目录结构:
aidl_api
└── android.hardware.automotive.helloworld
└── current
└── android
└── hardware
└── automotive
└── helloworld
└── IHelloworld.aidl
- 注意: 如果Android.bp中未设置owner,此步骤会报如下错误:
TODO: 添加错误消息
随后运行
mm android.hardware.automotive.helloworld-freeze-api
此命令会添加如下目录结构:
aidl_api
└── android.hardware.automotive.vapi
└── 1
└── android
└── hardware
└── automotive
└── vapi
├── IVapi.aidl
├── IVapiCallback.aidl
└── StatusCode.aidl
Android.bp会被自动更新为:
aidl_interface {
name: "android.hardware.automotive.helloworld",
vendor_available: true,
srcs: [
"android/hardware/automotive/helloworld/*.aidl",
],
stability: "vintf",
owner: "mycompany",
backend: {
java: {
platform_apis: true,
}
},
versions: ["1"], // <== 添加版本1
}
5. 实现AIDL接口
添加impl目录及实现代码, 目录结构如下
impl
├── Android.bp
└── helloworldhal
├── Android.bp
├── include
│ └── HelloworldHal.h
└── src
└── HelloworldHal.cpp
HelloworldHal.h
#ifndef android_hardware_automotive_vapi_aidl_impl_helloworldhal_include_HelloworldHal_H_
#define android_hardware_automotive_vapi_aidl_impl_helloworldhal_include_HelloworldHal_H_
#include <aidl/android/hardware/automotive/helloworld/BnHelloworld.h>
#include <android-base/expected.h>
#include <android-base/thread_annotations.h>
#include <android/binder_auto_utils.h>
namespace android {
namespace hardware {
namespace automotive {
namespace helloworld {
class HelloworldHal final : public aidl::android::hardware::automotive::helloworld::BnHelloworld {
public:
ndk::ScopedAStatus sayHello(
const std::string& name)
override;
};
} // namespace helloworld
} // namespace automotive
} // namespace hardware
} // namespace android
#endif // android_hardware_automotive_vapi_aidl_impl_helloworldhal_include_HelloworldHal_H_
HelloworldHal.cpp
#define ATRACE_TAG ATRACE_TAG_HAL
#include <HelloworldHal.h>
#include <android-base/result.h>
#include <android-base/stringprintf.h>
#include <android/binder_ibinder.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
#include <utils/Trace.h>
#include <inttypes.h>
#include <set>
#include <unordered_set>
namespace android {
namespace hardware {
namespace automotive {
namespace helloworld {
namespace {
using ::android::base::Error;
using ::android::base::expected;
using ::android::base::Result;
using ::android::base::StringPrintf;
using ::ndk::ScopedAIBinder_DeathRecipient;
using ::ndk::ScopedAStatus;
} // namespace
ndk::ScopedAStatus HelloworldHal::sayHello(
const std::string& name,
) {
return ScopedAStatus::ok();
}
} // namespace helloworld
} // namespace automotive
} // namespace hardware
} // namespace android
service.cpp
#define LOG_TAG "android.hardware.automotive.occupant_awareness@1.0-service"
#include <unistd.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include "OccupantAwareness.h"
using ::aidl::android::hardware::automotive::occupant_awareness::IOccupantAwareness;
using ::ndk::ScopedAStatus;
using ::ndk::SharedRefBase;
const static char kHelloworldServiceName[] = "default";
int main() {
ABinderProcess_setThreadPoolMaxThreadCount(0);
LOG(INFO) << "Helloworld service is starting";
std::shared_ptr<HelloworldHal> helloworldHal = SharedRefBase::make<HelloworldHal>();
const std::string instance =
std::string() + IHelloworldHal::descriptor + "/" + kHelloworldServiceName;
binder_status_t status =
AServiceManager_addService(helloworldHal->asBinder().get(), instance.c_str());
if (status == STATUS_OK) {
LOG(INFO) << "Service " << kHelloworldServiceName << " is ready";
ABinderProcess_joinThreadPool();
} else {
LOG(ERROR) << "Could not register service " << kHelloworldServiceName
<< ", status: " << status;
}
// In normal operation, we don't expect the thread pool to exit.
LOG(ERROR) << "Helloworld service is shutting down";
return 1;
}
helloworldhal/Android.bp
cc_binary {
name: "android.hardware.automotive.helloworld@1.0-service",
init_rc: ["android.hardware.automotive.helloworld@1.0-service.rc"],
relative_install_path: "hw",
vendor: true,
srcs: [
"service.cpp",
"HelloworldHal.cpp",
],
shared_libs: [
"libbase",
"libbinder_ndk",
"libutils",
"android.hardware.automotive.helloworld-ndk_platform",
],
}
Android.bp
package {
default_applicable_licenses: ["Android-Apache-2.0"],
}
cc_defaults {
name: "HelloworldHalDefaults",
static_libs: [
"libmath",
],
shared_libs: [
"libbase",
"liblog",
"libutils",
],
cflags: [
"-Wall",
"-Wextra",
"-Werror",
"-Wthread-safety",
],
defaults: [
"HelloworldHalInterfaceDefaults",
],
}
6. 编译
到 /hardware/interfaces/automotive/helloworld下,运行:
mm -j8
将会在 /out/target/product/trout_arm64/vendor/bin/hw 目录生成如下文件:
android.hardware.automotive.helloworld@1.0-service