在android15r17模拟器上实现的一个hal和hal client app示例

在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
  1. 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 -----------------------------------------------------------

相关推荐
Android系统攻城狮1 个月前
Android tinyalsa深度解析之pcm_params_get调用流程与实战(一百六十二)
android·pcm·tinyalsa·android hal·audio hal
Android系统攻城狮1 个月前
Android16进阶之MediaPlayer.setAudioAttributes调用流程与实战(二百三十六)
gitee·android16·音频进阶·android hal
Android系统攻城狮2 个月前
Android16进阶之MediaPlayer.isLooping调用流程与实战(二百三十二)
android16·音频进阶·android hal·audio hal·多媒体进阶
Android系统攻城狮2 个月前
Android16进阶之MediaPlayer.setLooping调用流程与实战(二百三十一)
android16·音频进阶·android hal·audio hal·多媒体进阶
Android系统攻城狮2 个月前
Android tinyalsa深度解析之pcm_set_avail_min调用流程与实战(一百二十二)
android·pcm·tinyalsa·音频进阶·android hal·audio hal
Android系统攻城狮2 个月前
Android tinyalsa深度解析之pcm_get_delay调用流程与实战(一百一十九)
android·pcm·tinyalsa·音频进阶·android hal·audio hal
Android系统攻城狮2 个月前
Android tinyalsa深度解析之pcm_get_timestamp调用流程与实战(一百一十八)
android·pcm·tinyalsa·android hal·audio hal
Android系统攻城狮3 个月前
Android tinyalsa深度解析之pcm_close调用流程与实战(一百零四)
android·pcm·tinyalsa·音频进阶·音频性能实战·android hal
Android系统攻城狮3 个月前
Android tinyalsa深度解析之pcm_open调用流程与实战(一百零三)
android·pcm·tinyalsa·音频进阶·音频性能实战·android hal