一、背景
车载项目中底层硬件会进行修改,硬件的相关接口需要暴漏给上层应用那么使用,比如车载音频中添加了一个外部DSP
,外部DSP
的相关音效、音量控制接口需要提供给上层,比如系统的设置应用中,应该有外部DSP
的音效设置。
二、方案
三、实现流程
3.1 编写AIDL
接口
- 因为是车载项目,将该接口定义在了
hardware/interfaces/automotive/mytest
下,需要注意的是编写的.aidl
文件不能直接放在mytest
目录下,需要符合规则,创建如下文件夹:
cd hardware/interfaces/automotive/mytest
mkdir -p android/hardware/automotive/mytest # 具体可以参考其他路径下的aidl的创建规则
touch android/hardware/automotive/mytest/IMyTest.aidl # 如果不按照这种嵌套文件夹创建最终生成出来的aidl有问题
- 下一步开始编写
aidl
文件,内容如下:
// 指定自定义接口的包名,这一行必须要有,后面需要使用,如果不写编译出来也是有问题的
package android.hardware.automotive.mytest;
@VintfStability
interface IMyTest {
oneway void test();
}
- 第三步是创建一个
Android.bp
并定义aidl
接口规则
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "hardware_interfaces_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["hardware_interfaces_license"],
}
// 这个package也是需要的,用于获取license
aidl_interface {
name: "android.hardware.automotive.mytest",
vendor_available: true,
owner: "android",
srcs: ["android/hardware/automotive/mytest/*.aidl"],
stability: "vintf",
// 指定需要生成的接口,这里制定了java接口和c++的ndk接口,也可以定义aidl的版本,
// 该文件中没有定义默认是v1
backend: {
java: {
enabled: true,
sdk_version: "module_current",
min_sdk_version: "31",
apex_available: [
"//apex_available:platform",
"com.android.car.framework",
],
},
ndk: {
enabled: true,
},
},
}
当前路径下的文件夹结构:
├── android
│ └── hardware
│ └── automotive
│ └── mytest
│ └── IMyTest.aidl
├── Android.bp
3.2 生成aidl api
接口
- 更新
API
;由于aidl
生成了接口是提供给上层应用的,因此需要先高速系统,当前增加了新的api
,也就是上面aidl
文件中定义的接口,更新接口使用如下命令:
m android.hardware.automotive.mytest-update-api
- 单编模块;
Android.bp
写完之后单编这个模块就会生成相应的接口文件,运行结束后目录结构如下:
.
├── aidl_api
│ └── android.hardware.automotive.mytest
│ └── current
│ └── android
│ └── hardware
│ └── automotive
│ └── mytest
│ └── IMyTest.aidl
├── android
│ └── hardware
│ └── automotive
│ └── mytest
│ └── IMyTest.aidl
├── Android.bp
生成的接口在out/soong/.intermediates/hardware/interfaces/automotive/mytest
目录下
四、接口应用——C++
文件结构如下,其中的default
是C++
服务的代码示例。
.
├── aidl_api
│ └── android.hardware.automotive.mytest
│ └── current
│ └── android
│ └── hardware
│ └── automotive
│ └── mytest
│ └── IMyTest.aidl
├── android
│ └── hardware
│ └── automotive
│ └── mytest
│ └── IMyTest.aidl
├── Android.bp
└── default
├── Android.bp
├── main.cpp
├── MyTest.cpp
├── mytest-default.rc
└── MyTest.h
下面是编译文件Android.bp
代码:
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "hardware_interfaces_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["hardware_interfaces_license"],
}
cc_binary {
name: "android.hardware.automotive.mytest.example",
relative_install_path: "hw",
vendor: true,
shared_libs: [
"android.hardware.automotive.mytest-V1-ndk", // 引用的是out目录下的ndk,主要就是这一行代码
"liblog",
"libbase",
"libcutils",
"libutils",
"libbinder_ndk",
],
srcs: [
"main.cpp",
"MyTest.cpp",
],
}
MyTest.h
#ifndef ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_MYTEST_H
#define ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_MYTEST_H
#include <aidl/android/hardware/automotive/mytest/BnMyTest.h>
namespace aidl::android::hardware::automotive::mytest {
class MyTest : public BnMyTest {
public:
MyTest();
::ndk::ScopedAStatus test() override;
};
} // namespace aidl::android::hardware::automotive::mytest
#endif // ANDROID_HARDWARE_AUTOMOTIVE_MYTEST_H
MyTest.cpp
#define LOG_TAG "MyTest"
// #define LOG_NDEBUG 0
#include "MyTest.h"
#include <android-base/logging.h>
#include <stdio.h>
namespace aidl::android::hardware::automotive::mytest {
MyTest::MyTest() {
}
ndk::ScopedAStatus MyTest::test() {
LOG(DEBUG) << "registering focus listener";
return ndk::ScopedAStatus::ok();
}
} // namespace aidl::android::hardware::automotive::mytest
main.cpp
#include "MyTest.h"
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
using aidl::android::hardware::automotive::mytest;
int main() {
ABinderProcess_setThreadPoolMaxThreadCount(0);
std::shared_ptr<MyTest> test = ::ndk::SharedRefBase::make<MyTest>();
const std::string instance = std::string() + MyTest::descriptor + "/default";
binder_status_t status =
AServiceManager_addService(test->asBinder().get(), instance.c_str());
CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
}
将该文件加入自启动中,需要添加下面的rc文件
service vendor.mytest-default /vendor/bin/hw/android.hardware.automotive.mytest.example
class hal
user root
group root
注意:这里将相应的服务放到了系统中并进行了自启动,会导致一些selinux相关的问题,需要另外进行解决。
五、整编
上面的流程每一笔单编都能编译通过,但是整编系统的时候会报错,原因是新添加的aidl
接口并没有加到配置文件中,在Android 13中配置文件有如下两个:
hardware/interfaces/compatibility_matrices/compatibility_matrix.current.xml
hardware/interfaces/compatibility_matrices/compatibility_matrix.7.xml
参照文件中的内容添加下面的信息即可:
<hal format="aidl" optional="true">
<name>android.hardware.automotive.mytest</name>
<version>1</version>
<interface>
<name>IMyTest</name>
<instance>default</instance>
</interface>
</hal>
六、测试
待补充