在android15r17模拟器上实现的一个hal和hal client app示例;
概述
本模块包含hal的aidl/sdk,进程service,hal进程发布的binder服务,以及一个调用hal sdk的示例app。
示例中的文件包含:
- aidl文件
- 进程主体cpp文件
- 定义sdk和可执行文件的Android.bp
- init进程启动用到的rc文件
sepolicy主体和te文件
工程源码已上传至:
https://download.csdn.net/download/Railshiqian/92826966
只需要把hello文件放在hardware/interfaces/下,并参考mk_changes.txt在device下进行对应配置,即可编译和运行hal和client进程。
我们按照以下流程来实现此hal.
1)实现aidl文件和对应Android.bp
2)实现service cpp和rc文件
3)添加必要se规则来实现hal进程启动和binder交互(赋予服务进程主体,定义binder服务主体,客户端获取binder服务,客户端和hal进程的binder交互规则)
4)修改device mk文件,将必须文件和se规则编译进img
file tree结构如下(aidl_api是通过编译自动生成的目录结构):
bash
aosp/android-15.0.0_r17/hardware/interfaces$ tree hello/
hello/
├── aidl
│ ├── aidl_api
│ │ └── android.hardware.hello
│ │ └── current
│ │ └── android
│ │ └── hardware
│ │ └── hello
│ │ ├── IHello.aidl
│ │ └── IHelloCallback.aidl
│ ├── android
│ │ └── hardware
│ │ └── hello
│ │ ├── IHello.aidl
│ │ └── IHelloCallback.aidl
│ └── Android.bp
├── ClientApp
│ ├── Android.bp
│ ├── AndroidManifest.xml
│ ├── res
│ │ └── layout
│ │ └── activity_main.xml
│ └── src
│ └── com
│ └── hello
│ └── test
│ └── MainActivity.java
├── default
│ ├── Android.bp
│ ├── compatibility_matrix.hello.202604.xml
│ ├── hello-default.xml
│ ├── HelloHal.cpp
│ └── hello_hal.rc
└── sepolicy
├── file_contexts
├── hello_hal.te
└── service_contexts
19 directories, 17 files
1,实现sdk/aidl并进行编译
我们要实现5个简单的接口get/set/regCallback/unregCallback/onValueChanged。
所以aidl接口定义如下:
IHello.aidl
bash
package android.hardware.hello;
import android.hardware.hello.IHelloCallback;
@VintfStability
interface IHello {
int get();
void set(int value);
void registerCallback(IHelloCallback cb);
void unregisterCallback(IHelloCallback cb);
}
IHelloCallback.aidl
bash
package android.hardware.hello;
/**
* Callback interface for HelloHal
*/
@VintfStability
interface IHelloCallback {
oneway void onValueChanged(int newValue);
}
Android.bp file:
bash
aidl_interface {
name: "android.hardware.hello",
srcs: [
"android/hardware/hello/IHello.aidl",
"android/hardware/hello/IHelloCallback.aidl",
],
vendor_available: true,
stability: "vintf",
backend: {
ndk: {
enabled: true,
},
java: {
enabled: true,
},
cpp: {
enabled: true,
},
},
frozen: false,
}
make android.hardware.hello-update-api 自动生成aidl_api文件夹和内容
make android.hardware.hello-V1-java 生成client需要用到的java sdk jar包。
可以把生成的jar包添加到modules dependence下,方便进行client app的编码工作。
out/soong/.intermediates/hardware/interfaces/hello/aidl/android.hardware.hello-V1-java/android_common/javac/android.hardware.hello-V1-java.jar
2,实现service cpp和rc文件文件
HelloHal.cpp内容:。
bash
#include <aidl/android/hardware/hello/BnHello.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <android-base/logging.h>
using aidl::android::hardware::hello::BnHello;
using aidl::android::hardware::hello::IHelloCallback;
using ndk::ScopedAStatus;
class HelloHal : public BnHello {
public:
HelloHal() : value_(0) {
LOG(INFO) << "HelloHal constructed";
}
ScopedAStatus get(int32_t* _aidl_return) override {
*_aidl_return = value_;
LOG(INFO) << "HelloHal.get() -> " << value_;
return ScopedAStatus::ok();
}
ScopedAStatus set(int32_t value) override {
value_ = value;
LOG(INFO) << "HelloHal.set(" << value << ")";
if (callback_) {
callback_->onValueChanged(value_);
}
return ScopedAStatus::ok();
}
ScopedAStatus registerCallback(
const std::shared_ptr<IHelloCallback>& cb) override {
callback_ = cb;
LOG(INFO) << "HelloHal callback registered";
return ScopedAStatus::ok();
}
ScopedAStatus unregisterCallback(
const std::shared_ptr<IHelloCallback>& cb) override {
if(callback_ == cb){
callback_ == 0;
}
LOG(INFO) << "HelloHal callback unregistered";
return ScopedAStatus::ok();
}
private:
int32_t value_;
std::shared_ptr<IHelloCallback> callback_;
};
int main() {
ABinderProcess_setThreadPoolMaxThreadCount(1);
auto service = ndk::SharedRefBase::make<HelloHal>();
const char* name =
"android.hardware.hello.IHello/default";
if (AServiceManager_addService(service->asBinder().get(), name)
!= STATUS_OK) {
LOG(FATAL) << "Failed to register HelloHal";
return -1;
}
LOG(INFO) << "HelloHal service started";
ABinderProcess_joinThreadPool();
return 0;
}
hello_hal.rc内容:
bash
service hello-hal /vendor/bin/hw/android.hardware.hello-service
class hal
user system
group system
oneshot
Android.bp内容:
bash
cc_binary {
name: "android.hardware.hello-service",
relative_install_path: "hw",
srcs: ["HelloHal.cpp"],
vintf_fragments: ["hello-default.xml"],
shared_libs: [
"libbinder_ndk",
"liblog",
"libbase",
"android.hardware.hello-V1-ndk",
],
vendor: true,
init_rc: ["hello_hal.rc"],
}
vintf_compatibility_matrix {
name: "framework_compatibility_matrix.hello.20206.xml",
stem: "compatibility_matrix.hello.202604.xml",
srcs: [
"compatibility_matrix.hello.202604.xml",
],
kernel_configs: [
"kernel_config_v_6.6",
],
}
SYSTEM_MATRIX_DEPS_HELLO = [
"framework_compatibility_matrix.hello.20206.xml",
]
phony {
name: "system_compatibility_matrix_hello.xml",
required: SYSTEM_MATRIX_DEPS_HELLO,
}
vintf device和framework兼容性文件。
hello-default.xml:
bash
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.hello</name>
<version>1</version>
<fqname>IHello/default</fqname>
</hal>
</manifest>
compatibility_matrix.hello.202604.xml:
bash
<compatibility-matrix version="1.0" type="framework" level="202604">
<hal format="aidl">
<name>android.hardware.hello</name>
<version>1</version>
<interface>
<name>IHello</name>
<instance>default</instance>
</interface>
</hal>
</compatibility-matrix>
3,Sepolicy定义
我们主要为以下三个主体定义SE规则:
1)hal进程实体
2)hal发布的binder实体
3)与binder/hal进程交互的client实体
所以包含以下规则文件:
1)hal进程文件和主体的关联规则文件file_contexts
bash
/vendor/bin/hw/android.hardware.hello-service u:object_r:hal_hello_default_exec:s0
2)hal binder服务和主体的关联规则文件service_contexts
bash
android.hardware.hello.IHello/default u:object_r:hal_hello_service:s0
- te规则文件hello_hal.te,定义了三方的交互规则
bash
attribute hal_hello;
expandattribute hal_hello true;
attribute hal_hello_client;
expandattribute hal_hello_client true;
attribute hal_hello_server;
expandattribute hal_hello_server false;
type hal_hello_default, domain;
hal_server_domain(hal_hello_default, hal_hello)
type hal_hello_default_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(hal_hello_default)
#binder server's context.
type hal_hello_service, service_manager_type;
#allow process get servicemanager binder.
allow hal_hello_default servicemanager:binder { call transfer };
#allow dumpstate dump my binder info.
allow dumpstate hal_hello_default:binder { call };
#allow platform_app binder call with hal_hello_default process.
binder_call(platform_app, hal_hello_default)
binder_call(hal_hello_default, platform_app)
#allow hal_hello_default process publish binder to service manager.
allow hal_hello_default hal_hello_service:service_manager add;
#allow platform app(with platform signature) use hal sdk.
allow platform_app hal_hello_service:service_manager { find };
binder_call(platform_app, hal_hello_service);
4,device mk 配置
bash
device/generic/car/sdk_car_md_x86_64.mk
PRODUCT_PACKAGES += \
android.hardware.hello-service \
system_compatibility_matrix_hello.xml
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS += \
hardware/interfaces/hello/sepolicy/
4,Sample app示例:
MainActivity.java:
java
package com.hello.test;
import android.app.Activity;
import android.hardware.hello.IHello;
import android.hardware.hello.IHelloCallback;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.view.View;
public class MainActivity extends Activity {
private IHello helloService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IBinder binder = ServiceManager.getService("android.hardware.hello.IHello/default");
helloService = IHello.Stub.asInterface(binder);
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("HelloHal", "onClick:");
try {
int value = helloService.get();
Log.d("HelloHal", "getvalue1:"+value);
value++;
helloService.set(value);
value = helloService.get();
Log.d("HelloHal", "getvalue2:"+value);
} catch (RemoteException e) {
Log.w("HelloHal", "click got exception.", e);;
}
}
});
}
private IHelloCallback helloCallback = new IHelloCallback.Stub() {
@Override
public void onValueChanged(int i) throws RemoteException {
Log.w("HelloHal", "onValueChanged i:"+i);;
}
@Override
public int getInterfaceVersion() throws RemoteException {
return 0;
}
@Override
public String getInterfaceHash() throws RemoteException {
return "";
}
};
@Override
protected void onResume() {
super.onResume();
try {
helloService.registerCallback(helloCallback);
} catch (RemoteException e) {
Log.w("HelloHal", "registerCallback failed.", e);
}
}
@Override
protected void onPause() {
super.onPause();
try {
helloService.unregisterCallback(helloCallback);
} catch (RemoteException e) {
Log.w("HelloHal", "unregisterCallback failed.", e);
}
}
}
Android.bp:
bash
android_app {
name: "HelloClientApp",
srcs: ["src/**/*.java"],
dex_preopt: {
enabled: false,
},
libs: [
],
static_libs: [
"android.hardware.hello-V1-java",
],
certificate: "platform",
// sdk_version: "module_current",
platform_apis: true,
}
---------------------------------------------- end line -----------------------------------------------------------