Android 13 AIDL服务编写

一、背景

车载项目中底层硬件会进行修改,硬件的相关接口需要暴漏给上层应用那么使用,比如车载音频中添加了一个外部DSP,外部DSP的相关音效、音量控制接口需要提供给上层,比如系统的设置应用中,应该有外部DSP的音效设置。

二、方案

service调用硬件驱动的具体接口
APP
HAL_service
硬件驱动
硬件

三、实现流程

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++

文件结构如下,其中的defaultC++服务的代码示例。

.
├── 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>

六、测试

待补充

  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
学习Android AIDL编写,可以参考以下步骤: 1. 定义AIDL接口文件:在Android Studio中创建一个新的AIDL文件,定义接口名称和方法,例如: ``` interface IMyAidlInterface { void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); } ``` 2. 实现AIDL接口:创建一个Service并实现定义的AIDL接口,例如: ``` public class MyAidlService extends Service { private final IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) { // 实现接口方法 } }; @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } } ``` 3. 绑定AIDL服务:在客户端中绑定AIDL服务,例如: ``` private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 获取AIDL接口实例 IMyAidlInterface myAidlInterface = IMyAidlInterface.Stub.asInterface(service); try { // 调用AIDL接口方法 myAidlInterface.basicTypes(1, 2, true, 1.0f, 2.0, "test"); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; Intent intent = new Intent(); intent.setComponent(new ComponentName("com.example.myapp", "com.example.myapp.MyAidlService")); bindService(intent, mConnection, BIND_AUTO_CREATE); ``` 这些步骤可以帮助您开始学习Android AIDL编写。当然,还有更多高级的功能和用法,可以在进一步学习中探索。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值