Hal aidl 模板
目录
背景:在AOSP14,模拟器下编写
1. 创建aidl目录
2. 创建对应的aidl文件
3.编写aidl Android.bp
4. 编译aidl
5. 编写aidl服务端
6.将模块加入到兼容性矩阵中
8. 编写SELinux权限
8.1添加接口SE类型
8.2添加可执行程序SE类型
8.3定义这些类型并添加策略
9. 将模块加入到整机编译
10. 使用testcmd测试
11. 编写App进行测试
背景:在AOSP14,模拟器下编写
source build/envsetup.sh
lunch sdk_phone64_x86_64-trunk_staging-eng
1. 创建aidl目录
mkdir -p hardware/interfaces/mycmd/aidl
cd hardware/interfaces/mycmd/aidl
mkdir -p android/hardware/mycmd/
android/hardware/mycmd/目录其实就是包名,即android.hardware.mycmd
2. 创建对应的aidl文件
android/
└── hardware
└── mycmd
├── IMyCmd.aidl
└── MyCmdObj.aidl
IMyCmd.aidl
package android.hardware.mycmd;
import android.hardware.mycmd.MyCmdObj;@VintfStability
interface IMyCmd {int exeCmd(in MyCmdObj cmd);
}
MyCmdObj.aidl
package android.hardware.mycmd;
@VintfStabilityparcelable MyCmdObj {String cmd;
}
3.编写aidl Android.bp
touch hardware/interfaces/mycmd/aidl/Android.bp
Android.bp
aidl_interface {name: "android.hardware.mycmd",vendor_available: true,srcs: ["android/hardware/mycmd/*.aidl"],stability: "vintf",owner: "cchao",backend: {cpp: {enabled: false,},java: {sdk_version: "module_current",},},
}
4. 编译aidl
cd hardware/interfaces/mycmd/aidl/
mm -j12
如果出现以下错误,先执行m android.hardware.mycmd-update-api,再重新编译
编译完成后生成如下目录
└── aidl
├── aidl_api
│ └── android.hardware.mycmd
│ └── current
│ └── android
│ └── hardware
│ └── mycmd
│ ├── IMyCmd.aidl
│ └── MyCmdObj.aidl
├── android
│ └── hardware
│ └── mycmd
│ ├── IMyCmd.aidl
│ └── MyCmdObj.aidl
├── Android.bp
并且生成相应的库,目录在out下out/soong/.intermediates/hardware/interfaces/mycmd/aidl
包括Java和NDK的接口文件和库文件
5. 编写aidl服务端
mkdir hardware/interfaces/mycmd/aidl/default/
先创建好对应的文件
default/
├── Android.bp
├── android.hardware.mycmd.rc
├── main.cpp
├── mycmd-default.xml
├── MyCmdImpl.cpp
└── MyCmdImpl.h
Android.bp
cc_binary {name: "android.hardware.mycmd.service",relative_install_path: "hw",vendor: true,init_rc: ["android.hardware.mycmd.rc"],vintf_fragments: ["mycmd-default.xml"],shared_libs: ["android.hardware.mycmd-V1-ndk","liblog","libbase","libcutils","libutils","libbinder_ndk",],srcs: ["main.cpp","MyCmdImpl.cpp",],
}
android.hardware.mycmd.rc
service vendor.mycmd-default /vendor/bin/hw/android.hardware.mycmd.serviceclass haluser rootgroup root
MyCmdImpl.cpp
#define LOG_TAG "MyCmdImpl"
#define LOG_NDEBUG 0#include "MyCmdImpl.h"#include <log/log.h>
#include <android-base/logging.h>#include <stdio.h>namespace aidl::android::hardware::mycmd {::ndk::ScopedAStatus MyCmdImpl::exeCmd(const ::aidl::android::hardware::mycmd::MyCmdObj &obj, int * _aidl_return) {*_aidl_return = 1;LOG(INFO) << " MyCmdImpl::eceCmd " << obj.cmd.c_str();return ::ndk::ScopedAStatus::ok();
}} // namespace aidl::android::hardware::mycmd
MyCmdImpl.h
#ifndef ANDROID_HARDWARE_MYCMDIMPL_H
#define ANDROID_HARDWARE_MYCMDIMPL_H#include <aidl/android/hardware/mycmd/BnMyCmd.h>namespace aidl::android::hardware::mycmd {class MyCmdImpl : public BnMyCmd {public:::ndk::ScopedAStatus exeCmd(const ::aidl::android::hardware::mycmd::MyCmdObj &obj, int * _aidl_return) override;};} // namespace aidl::android::hardware::mycmd#endif
main.cpp
#include "MyCmdImpl.h"
#define LOG_TAG "MyCmdImpl"
#define LOG_NDEBUG 0
#include <iostream>#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>#include <stdio.h>using aidl::android::hardware::mycmd::MyCmdImpl;int main(){ABinderProcess_setThreadPoolMaxThreadCount(0);std::shared_ptr<MyCmdImpl> test = ::ndk::SharedRefBase::make<MyCmdImpl>();const std::string instance = std::string() + MyCmdImpl::descriptor + "/default";LOG(INFO) << "MyCmdImpl instance " << instance.c_str();binder_status_t status = AServiceManager_addService(test->asBinder().get(), instance.c_str());CHECK_EQ(status, STATUS_OK);LOG(INFO) << "MyCmdImpl status " << status;ABinderProcess_joinThreadPool();return EXIT_FAILURE;
}
mycmd-default.xml
<manifest version="1.0" type="device"><hal format="aidl"><name>android.hardware.mycmd</name><version>1</version><interface><name>IMyCmd</name><instance>default</instance></interface></hal>
</manifest>
编译server端
cd hardware/interfaces/mycmd/aidl/default
mm -j12
编译完成后生成如下文件
out/target/product/emu64x/vendor/etc/vintf/manifest/mycmd-default.xml
out/target/product/emu64x/vendor/etc/init/android.hardware.mycmd.rc
out/target/product/emu64x/vendor/bin/hw/android.hardware.mycmd.service
6.将模块加入到兼容性矩阵中
cd hardware/interfaces/compatibility_matrices
加到最新的一个文件中
<hal format="aidl"><name>android.hardware.mycmd</name><version>1</version><interface><name>IMyCmd</name><instance>default</instance></interface></hal>
7. 编写测试程序
mkdir hardware/interfaces/mycmd/aidl/testcmd
testcmd/
├── Android.bp
└── main.cpp
Android.bp
cc_binary {name: "testcmd",shared_libs: ["android.hardware.mycmd-V1-ndk","liblog","libbase","libcutils","libutils","libbinder_ndk",],srcs: ["main.cpp",],vendor: true,
}
main.cpp
#define LOG_TAG "Test-HAL"
#define LOG_NDEBUG 0
#include <iostream>#include <log/log.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <aidl/android/hardware/mycmd/IMyCmd.h>
#include <android-base/logging.h>#include <stdio.h>
using aidl::android::hardware::mycmd::IMyCmd;int main() {LOG(INFO) << "hal test mycmd main";std::shared_ptr<IMyCmd> service = IMyCmd::fromBinder(ndk::SpAIBinder(AServiceManager_getService("android.hardware.mycmd.IMyCmd/default")));LOG(INFO) << "my service";if(service == nullptr){LOG(INFO) << "service is null";return -1;}int result = 0;::aidl::android::hardware::mycmd::MyCmdObj obj;obj.cmd = "logcat";service->exeCmd(obj, &result);LOG(INFO) << "return value " << result;return EXIT_FAILURE;
}
8. 编写SELinux权限
cd device/generic/goldfish/sepolicy/vendor/
8.1添加接口SE类型
service_contexts
android.hardware.mycmd.IMyCmd/default u:object_r:hal_mycmd_service:s0
hwservice_contexts
android.hardware.mycmd::IMyCmd u:object_r:hal_mycmd_hwservice:s0
8.2添加可执行程序SE类型
file_contexts
/(vendor|system/vendor)/bin/hw/android\.hardware\.mycmd\.service u:object_r:hal_mycmd_server_exec:s0
/(vendor|system/vendor)/bin/testcmd u:object_r:hal_mycmd_client_exec:s0
8.3定义这些类型并添加策略
hal_mycmd_server.te
type hal_mycmd_server, domain, mlstrustedsubject;
type hal_mycmd_server_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(hal_mycmd_server);type hal_mycmd_client, domain, mlstrustedsubject;
type hal_mycmd_client_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(hal_mycmd_client);binder_call(hal_mycmd_client, hal_mycmd_server)type hal_mycmd_service, service_manager_type;
type hal_mycmd_hwservice, hwservice_manager_type, protected_hwservice;add_service(hal_mycmd_server, hal_mycmd_service)
add_hwservice(hal_mycmd_server, hal_mycmd_hwservice)allow hal_mycmd_client hal_mycmd_hwservice:hwservice_manager find;allow hal_mycmd_server servicemanager:binder {call transfer };allow system_app hal_mycmd_server:binder { call };
9. 将模块加入到整机编译
vi device/generic/goldfish/board/emu64x/details.mk
PRODUCT_PACKAGES += \android.hardware.mycmd \android.hardware.mycmd.service \testcmd
10. 使用testcmd测试
08-29 17:17:33.582 2237 2237 I Test-HAL: hal test mycmd main
08-29 17:17:33.584 2237 2237 I Test-HAL: my service
08-29 17:17:33.584 318 318 I MyCmdImpl: MyCmdImpl::exeCmd logcat
08-29 17:17:33.584 2237 2237 I Test-HAL: return value 1
11. 编写App进行测试
将out/soong/.intermediates/hardware/interfaces/mycmd/aidl/android.hardware.mycmd-V1-java/android_common/javac/android.hardware.mycmd-V1-java.jar拷贝到工程app/libs/下
build.gradle.kts中添加
implementation(files("libs/android.hardware.mycmd-V1-java.jar")
编写Java测试代码
private void runServiceCmd(){IBinder binder = getService("android.hardware.mycmd.IMyCmd/default");IMyCmd test = IMyCmd.Stub.asInterface(binder);Log.d(TAG, "binder: " + test);try {MyCmdObj obj = new MyCmdObj();obj.cmd = "logcat";int result = test.exeCmd(obj);Log.d(TAG, "Result message: " + result);} catch (Exception e) {e.printStackTrace();}}public static IBinder getService(String name) {try {Class<?> c = Class.forName("android.os.ServiceManager");Method getService = c.getMethod("getService", String.class);return (IBinder) getService.invoke(c, name);} catch (Exception e) {e.printStackTrace();return null;}}
测试结果
08-29 18:27:45.320 2285 2285 D CCDEBUG : binder: android.hardware.mycmd.IMyCmd$Stub$Proxy@319fd6
08-29 18:27:45.321 318 318 I MyCmdImpl: MyCmdImpl::eceCmd logcat
08-29 18:27:45.323 2285 2285 D CCDEBUG : Result message: 1