创建一个aidl demo工程
创建的目录结构如下:
root@2f9414cb61fd:/aosp/packages/modules/DemoAidl# tree
.
|-- Android.bp
|-- aidl
| `-- com
| `-- example
| `-- demo
| |-- IDemo.aidl
| `-- IDemoCallback.aidl
|-- client
| `-- main.cpp
|-- demo_service.rc
`-- service
|-- DemoService.cpp
|-- DemoService.h
`-- main.cppIDemo.aidl内容如下:
package com.example.demo;
import com.example.demo.IDemoCallback;
interface IDemo {
int add(int a, int b);
void registerCallback(IDemoCallback callback);
void unregisterCallback(IDemoCallback callback);
void triggerCallback(int value);
}IDemoCallback.aidl内容如下:
package com.example.demo;
interface IDemoCallback {
void onValueChanged(int value);
}client/main.cpp内容如下:
#include <aidl/com/example/demo/BnDemoCallback.h>
#include <aidl/com/example/demo/IDemo.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <log/log.h>
#include <iostream>
#include <memory>
#include <string>
using aidl::com::example::demo::BnDemoCallback;
using aidl::com::example::demo::IDemo;
class DemoCallback : public BnDemoCallback {
public:
ndk::ScopedAStatus onValueChanged(
int32_t value) override {
ALOGI(
"Callback received value=%d",
value);
std::cout
<< "[Callback] value = "
<< value
<< std::endl;
return ndk::ScopedAStatus::ok();
}
};
int main() {
std::cout << "Demo client starting..."
<< std::endl;
// ------------------------------------------------
// 1. 获取 service
// ------------------------------------------------
std::string instance =
std::string(IDemo::descriptor) +
"/default";
std::cout
<< "Waiting for service: "
<< instance
<< std::endl;
ndk::SpAIBinder binder =
ndk::SpAIBinder(
AServiceManager_waitForService(
instance.c_str()));
if (binder == nullptr) {
std::cerr
<< "Failed to get service"
<< std::endl;
return 1;
}
// ------------------------------------------------
// 2. 转换成 AIDL interface
// ------------------------------------------------
std::shared_ptr<IDemo> service =
IDemo::fromBinder(binder);
if (service == nullptr) {
std::cerr
<< "Failed to create IDemo"
<< std::endl;
return 1;
}
std::cout
<< "Connected to service"
<< std::endl;
// ------------------------------------------------
// 3. 普通函数调用
// ------------------------------------------------
int32_t result = 0;
auto status =
service->add(
10,
20,
&result);
if (!status.isOk()) {
std::cerr
<< "add() failed: "
<< status.getDescription()
<< std::endl;
return 1;
}
std::cout
<< "add(10, 20) = "
<< result
<< std::endl;
// ------------------------------------------------
// 4. 创建 callback
// ------------------------------------------------
auto callback =
ndk::SharedRefBase::make<DemoCallback>();
// ------------------------------------------------
// 5. 注册 callback
// ------------------------------------------------
status =
service->registerCallback(
callback);
if (!status.isOk()) {
std::cerr
<< "registerCallback failed: "
<< status.getDescription()
<< std::endl;
return 1;
}
std::cout
<< "Callback registered"
<< std::endl;
// ------------------------------------------------
// 6. 触发 callback
// ------------------------------------------------
for (int i = 0; i < 5; ++i) {
int value = i * 100;
std::cout
<< "Trigger callback: "
<< value
<< std::endl;
status =
service->triggerCallback(
value);
if (!status.isOk()) {
std::cerr
<< "triggerCallback failed: "
<< status.getDescription()
<< std::endl;
}
}
// ------------------------------------------------
// 7. 注销 callback
// ------------------------------------------------
status =
service->unregisterCallback(
callback);
if (!status.isOk()) {
std::cerr
<< "unregisterCallback failed"
<< std::endl;
return 1;
}
std::cout
<< "Callback unregistered"
<< std::endl;
return 0;
}DemoService.cpp内容如下:
#include "DemoService.h"
#include <android/binder_ibinder.h>
#include <log/log.h>
namespace aidl::com::example::demo {
ndk::ScopedAStatus DemoService::add(
int32_t a,
int32_t b,
int32_t* _aidl_return) {
*_aidl_return = a + b;
ALOGI("add(%d, %d) = %d",
a,
b,
*_aidl_return);
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus DemoService::registerCallback(
const std::shared_ptr<IDemoCallback>& callback) {
if (callback == nullptr) {
ALOGE("registerCallback: callback is null");
return ndk::ScopedAStatus::fromExceptionCode(
EX_NULL_POINTER);
}
std::lock_guard<std::mutex> lock(mMutex);
mCallbacks.push_back(callback);
ALOGI("callback registered, total=%zu",
mCallbacks.size());
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus DemoService::unregisterCallback(
const std::shared_ptr<IDemoCallback>& callback) {
if (callback == nullptr) {
return ndk::ScopedAStatus::fromExceptionCode(
EX_NULL_POINTER);
}
std::lock_guard<std::mutex> lock(mMutex);
for (auto it = mCallbacks.begin();
it != mCallbacks.end();
++it) {
if ((*it)->asBinder() == callback->asBinder()) {
mCallbacks.erase(it);
ALOGI("callback unregistered, total=%zu",
mCallbacks.size());
return ndk::ScopedAStatus::ok();
}
}
ALOGW("callback not found");
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus DemoService::triggerCallback(
int32_t value) {
std::vector<std::shared_ptr<IDemoCallback>> callbacks;
{
std::lock_guard<std::mutex> lock(mMutex);
callbacks = mCallbacks;
}
ALOGI("triggerCallback(%d), callback count=%zu",
value,
callbacks.size());
for (const auto& callback : callbacks) {
if (callback == nullptr) {
continue;
}
auto status = callback->onValueChanged(value);
if (!status.isOk()) {
ALOGE("callback failed: %s",
status.getDescription().c_str());
}
}
return ndk::ScopedAStatus::ok();
}
} // namespace aidl::com::example::demo
DemoService.h内容如下:
#pragma once
#include <aidl/com/example/demo/BnDemo.h>
#include <aidl/com/example/demo/IDemoCallback.h>
#include <memory>
#include <mutex>
#include <vector>
namespace aidl::com::example::demo {
class DemoService : public BnDemo {
public:
DemoService() = default;
~DemoService() override = default;
ndk::ScopedAStatus add(
int32_t a,
int32_t b,
int32_t* _aidl_return) override;
ndk::ScopedAStatus registerCallback(
const std::shared_ptr<IDemoCallback>& callback) override;
ndk::ScopedAStatus unregisterCallback(
const std::shared_ptr<IDemoCallback>& callback) override;
ndk::ScopedAStatus triggerCallback(
int32_t value) override;
private:
std::mutex mMutex;
std::vector<std::shared_ptr<IDemoCallback>> mCallbacks;
};
} // namespace aidl::com::example::demoservice/main.cpp 内容如下:
#include "DemoService.h"
#include <aidl/com/example/demo/IDemo.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <log/log.h>
using aidl::com::example::demo::DemoService;
using aidl::com::example::demo::IDemo;
int main() {
ALOGI("Starting demo service");
// 设置 Binder 线程池
ABinderProcess_setThreadPoolMaxThreadCount(4);
// 创建 service
auto service = ndk::SharedRefBase::make<DemoService>();
// 服务名
std::string instance =
std::string(IDemo::descriptor) + "/default";
ALOGI("Register service: %s",
instance.c_str());
// 注册到 servicemanager
binder_status_t status =
AServiceManager_addService(
service->asBinder().get(),
instance.c_str());
if (status != STATUS_OK) {
ALOGE("Failed to register service: %d",
status);
return 1;
}
ALOGI("Demo service registered");
// 进入 Binder 线程池
ABinderProcess_joinThreadPool();
return 0;
}Android.bp内容如下:
aidl_interface {
name: "demo-aidl",
srcs: [
"aidl/com/example/demo/*.aidl",
],
local_include_dir: "aidl",
unstable: true,
vendor_available: true,
backend: {
java: {
enabled: false,
},
cpp: {
enabled: false,
},
ndk: {
enabled: true,
},
},
}
cc_binary {
name: "demo_service",
srcs: [
"service/DemoService.cpp",
"service/main.cpp",
],
shared_libs: [
"libbinder_ndk",
"liblog",
],
static_libs: [
"demo-aidl-ndk",
],
vendor: true,
init_rc: [
"demo_service.rc",
],
cflags: [
"-Wall",
"-Wextra",
],
}
cc_binary {
name: "demo_client",
srcs: [
"client/main.cpp",
],
shared_libs: [
"libbinder_ndk",
"liblog",
],
static_libs: [
"demo-aidl-ndk",
],
vendor: true,
cflags: [
"-Wall",
"-Wextra",
],
}demo_service.rc内容如下
service demo_service /vendor/bin/demo_service
class main
user system
group system将创建的服务加入系统服务中
打开 device_vendor.mk 文件,在文件末尾添加创建的服务
# 1. 进入工程目录
cd /aosp
# 2. 修改 device_vendor.mk,末尾添加 demo_service 加入自启动服务中
vim device/google/cuttlefish/shared/auto/device_vendor.mk
PRODUCT_PACKAGES += CarServiceOverlayCuttleFish
GOOGLE_CAR_SERVICE_OVERLAY += CarServiceOverlayCuttleFishGoogle
PRODUCT_PACKAGES += ConnectivityOverlayCuttleFish
GOOGLE_CAR_SERVICE_OVERLAY += ConnectivityOverlayCuttleFishGoogle
TARGET_BOARD_INFO_FILE ?= device/google/cuttlefish/shared/auto/android-info.txt
[++++++] PRODUCT_PACKAGES += \
[++++++] demo_serviceSELinux 策略层问题解决
打开
cd /aosp
cd device/google/cuttlefish/shared/sepolicy/vendor
# 1. 修改 service_contexts
vim service_contexts
[++++++] com.example.demo.IDemo u:object_r:demo_service_service:s0
[++++++] com.example.demo.IDemo/default u:object_r:demo_service_service:s0
# 2. 修改 demo_service.te
vim demo_service.te
[++++++] type demo_service, domain;
[++++++] type demo_service_exec, exec_type, vendor_file_type, file_type;
[++++++] type demo_service_service, service_manager_type;
[++++++] init_daemon_domain(demo_service)
[++++++] binder_use(demo_service)
[++++++] allow demo_service demo_service:binder { call transfer };
[++++++] allow demo_service servicemanager:binder { call transfer };
[++++++] allow demo_service demo_service_service:service_manager { add find };
# 3. 修改 file_contexts
vim file_contexts
/vendor/lib(64)?/hw/android\.hardware\.health@2\.0-impl-2\.1-cuttlefish\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/libcuttlefish_fs.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/vsoc_lib.so u:object_r:same_process_hal_file:s0
[++++++] /vendor/bin/demo_service u:object_r:demo_service_exec:s0开始测试
进入aosp环境,执行编译操作
source build/envsetup.sh
lunch aosp_cf_x86_64_auto-trunk_staging-userdebug
编译成功后,打开 cuttlefish docker 环境,进入其中进行测试,cuttlefish docker的部署可参照: 使用cuttlefish虚拟机测试AOSP程序
# 1. 进入 cuttlefish 容器中
sudo docker compose exec cuttlefish-common bash
# 2. 启动虚拟机
launch_cvd --system_image_dir=/aosp-out/target/product/vsoc_x86_64_only
# 3. 启动成功后,在另外一个终端执行,即可看到服务正常启动运行
adb connect 127.0.0.1:6520
adb root
adb shell getprop init.svc.demo_service
adb shell service list | grep -i demo
adb shell dmesg | grep -i avc | grep demo
