android 新增native binder service 方式(一)
关于之前说的native service 之前有写过类似的文章,今天主要介绍下如何通过binder 方式跨进程调用和回调,结合网上的各种文章,总结了3种常见的添加方式,供大家参考。
一,aidl 文件定义
先看下整体的目录结构
libserviceaidl 就是我定义的aidi接口
IService.aidl
package com.test;
import com.test.IServiceCallback;
interface IService {
void registerCallback(IServiceCallback callback);
void call(int type);
int callMcu(int file,in byte[] type);
}
IServiceCallback.aidl
package com.test;
interface IServiceCallback{
void onEventString(int eventCode, String eventMessage);
void onEventbyte(out byte[] data);
}
通过Android.bp 编译成so
cc_library_shared {
name: "libserviceaidl",
aidl: {
export_aidl_headers: true,
local_include_dirs: ["aidl"],
include_dirs: [
],
},
srcs: [
":serviceaidl",
],
shared_libs: [
"libbase",
"libcutils",
"libutils",
"liblog",
"libbinder",
"libgui",
],
cflags: [
"-Werror",
"-Wall",
"-Wextra",
],
}
filegroup {
name: "serviceaidl",
srcs: [
"aidl/com/test/IService.aidl",
"aidl/com/test/IServiceCallback.aidl",
],
path: "aidl",
}
make libserviceaidl
会生成libserviceaidl.so ,需要push 到我们系统对应目录,这样调用的binder 库就定义好了。
二,编译Native service
Android.bp 添加aidl 库依赖
cc_binary {
name: "testservverfirst",
srcs: ["servertest.cpp",
],
shared_libs: [
"liblog",
"libcutils",
"libutils",
"libbinder",
"libserviceaidl",// 上面编译生成的
],
init_rc: ["testservver.rc"],
}
cc_binary {
name: "clienttest",
srcs: ["clienttest.cpp",
],
shared_libs: [
"liblog",
"libcutils",
"libutils",
"libbinder",
"libserviceaidl",
],
}
servertest.cpp 源文件
#define LOG_TAG "testservverfirst"
#include <log/log.h>
#include <unistd.h>
#include <stdlib.h>
#include <utils/RefBase.h>
#include <utils/Log.h>
#include <binder/TextOutput.h>
#include <binder/IInterface.h>
#include <binder/IBinder.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <termios.h>
#include <utils/String16.h>
#include <com/test/BnService.h>
using namespace std;
using namespace android;
class TestService : public com::test::BnService
{
public:
TestService(){
}
binder::Status nativecall(int i)
{
ALOGI("server nativecall function is running %d",i);
if(mycallback != nullptr){
mycallback->onEventString(4,String16("callbacksuccuess"));
}
return binder::Status();
}
binder::Status callMcu(int32_t file,const vector<uint8_t>& type, int32_t* _aidl_return){
*_aidl_return = 1;
ALOGI("server callMcu function is running _aidl_return",*_aidl_return);
return binder::Status();
}
binder::Status call(int32_t type){
ALOGI("server call function is running call",type);
return binder::Status();
}
// 实现回调注册
binder::Status registerCallback(const sp<com::test::IServiceCallback>& callback){
mycallback = callback;
return binder::Status();
}
private:
sp<::com::test::IServiceCallback> mycallback;
};
int main(int argc, char const *argv[])
{
ALOGD("Server is runing");
//发布服务
defaultServiceManager()->addService(String16("TestService"), new TestService());
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
编译testservverfirst ,会生成testservverfirst 可执行文件,我们push 到系统/system/bin/ 下
手动执行:./system/bin/testservverfirst 会看到
01-18 17:59:16.174 4144 4144 D testservverfirst: Server is runing
说明我们的native service 运行成功了,也可以通过命令查看:
查看native service 是否运行成功
device:/ # ps -A| grep testservverfirst
root 4144 3449 15340 4952 binder_ioctl_write_read 0 S testservverfirst
查看binder service 是否运行成功
130|monaco_go:/ # dumpsys | grep TestService,
--------- 0.009s was the duration of dumpsys TestService, ending at: 2025-01-18 18:18:52
三,编译client
我们编译一个client 来本地验证下,binder 通信是否成功
make clienttest
#define LOG_TAG "clienttest"
#include <log/log.h>
#include <stdlib.h>
#include <utils/RefBase.h>
#include <utils/Log.h>
#include <binder/TextOutput.h>
#include <binder/IInterface.h>
#include <binder/IBinder.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <com/test/BnService.h>
using namespace android;
int main(int argc, char const *argv[])
{
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("TestService"));
sp<com::test::IService> simservice = interface_cast<com::test::IService>(binder);
simservice->call(3);
return 0;
}
生成的clienttest ,push 到系统system/bin/,手动执行 ./system/bin/clienttest,查看service 的log
01-18 18:00:25.336 4144 4145 I testservverfirst: server call function is running call
说明调用成功了。
四,添加开机启动
这里我们加了一个rc 文件,开机会解析。
testservver.rc
on post-fs
chown system system /system/bin/testservverfirst
chmod 0777 /system/bin/testservverfirst
restorecon_recursive /system/bin/testservverfirst
service testservverfirst /system/bin/testservverfirst
class core
console
disabled
seclabel u:r:su:s0
on property:sys.xss=2
setprop xss.home 2
start testservverfirst
on property:sys.boot_completed=1
start testservverfirst
这里我们监听sys.boot_completed 开机完成的属性,来启动服务,还有其他的方式,参考之前写的文章
Android 新增可执行脚本方式总结_android脚本-CSDN博客
五,增加selinux 权限
上面四个步骤,我们走完过后,发现开机服务是启动不了的,因为缺少selinux 权限,这个之前文章也介绍过,这个需要耐心,慢慢添加,大概步骤如下。
主要修改
file_contexts 添加native service 标签
testservverfirst.te 添加native 权限
service.te 添加binder service 类型
service_contexts 添加binder service 标签
调试的时候记得先关闭selinux 这样方便一次性把权限都加完。
diff --git a/prebuilts/api/30.0/private/testservverfirst.te b/prebuilts/api/30.0/private/testservverfirst.te
new file mode 100644
index 0000000..5a72981
--- /dev/null
+++ b/prebuilts/api/30.0/private/testservverfirst.te
@@ -0,0 +1,15 @@
+type testservverfirst, domain,mlstrustedsubject;
+typeattribute testservverfirst coredomain;
+type testservverfirst_exec, system_file_type, exec_type, file_type;
+binder_use(testservverfirst)
+init_daemon_domain(testservverfirst)
+
+allow testservverfirst servicemanager:binder { call transfer };
+allow testservverfirst testservverfirst_service:service_manager { add find };
+allow testservverfirst tty_device:chr_file { read write };
+allow testservverfirst untrusted_app:binder call;
+
+binder_use(testservverfirst)
+add_service(testservverfirst,testservverfirst_service)
+
+
diff --git a/prebuilts/api/30.0/private/file_contexts b/prebuilts/api/30.0/private/file_contexts
index b774920..37049f6 100644
--- a/prebuilts/api/30.0/private/file_contexts
+++ b/prebuilts/api/30.0/private/file_contexts
@@ -738,3 +738,4 @@
#############################
# mount point for read-write product partitions
/mnt/product(/.*)? u:object_r:mnt_product_file:s0
+/system/bin/testservverfirst u:object_r:testservverfirst_exec:s0
diff --git a/prebuilts/api/30.0/private/service.te b/prebuilts/api/30.0/private/service.te
index 6c17521..77d585a 100644
--- a/prebuilts/api/30.0/private/service.te
+++ b/prebuilts/api/30.0/private/service.te
@@ -6,3 +6,4 @@
type statscompanion_service, system_server_service, service_manager_type;
type statsmanager_service, system_api_service, system_server_service, service_manager_type;
type uce_service, service_manager_type;
+type testservverfirst_service, service_manager_type;
diff --git a/prebuilts/api/30.0/private/service_contexts b/prebuilts/api/30.0/private/service_contexts
index 7c9f396..c1687f7 100644
--- a/prebuilts/api/30.0/private/service_contexts
+++ b/prebuilts/api/30.0/private/service_contexts
@@ -249,3 +249,4 @@
window u:object_r:window_service:s0
glasses u:object_r:sim_glasses_service:s0
* u:object_r:default_android_service:s0
+TestService u:object_r:testservverfirst_service:s0
diff --git a/prebuilts/api/30.0/private/untrusted_app.te b/prebuilts/api/30.0/private/untrusted_app.te
index 6e7a99c..97a84e3 100644
--- a/prebuilts/api/30.0/private/untrusted_app.te
+++ b/prebuilts/api/30.0/private/untrusted_app.te
@@ -14,3 +14,5 @@
untrusted_app_domain(untrusted_app)
net_domain(untrusted_app)
bluetooth_domain(untrusted_app)
+allow untrusted_app testservverfirst:binder { transfer call };
+allow untrusted_app testservverfirst_service:service_manager find;
diff --git a/private/testservverfirst.te b/private/testservverfirst.te
new file mode 100644
index 0000000..5a72981
--- /dev/null
+++ b/private/testservverfirst.te
@@ -0,0 +1,15 @@
+type testservverfirst, domain,mlstrustedsubject;
+typeattribute testservverfirst coredomain;
+type testservverfirst_exec, system_file_type, exec_type, file_type;
+binder_use(testservverfirst)
+init_daemon_domain(testservverfirst)
+
+allow testservverfirst servicemanager:binder { call transfer };
+allow testservverfirst testservverfirst_service:service_manager { add find };
+allow testservverfirst tty_device:chr_file { read write };
+allow testservverfirst untrusted_app:binder call;
+
+binder_use(testservverfirst)
+add_service(testservverfirst,testservverfirst_service)
+
+
diff --git a/private/file_contexts b/private/file_contexts
index b774920..37049f6 100644
--- a/private/file_contexts
+++ b/private/file_contexts
@@ -738,3 +738,4 @@
#############################
# mount point for read-write product partitions
/mnt/product(/.*)? u:object_r:mnt_product_file:s0
+/system/bin/testservverfirst u:object_r:testservverfirst_exec:s0
diff --git a/private/service.te b/private/service.te
index 6c17521..77d585a 100644
--- a/private/service.te
+++ b/private/service.te
@@ -6,3 +6,4 @@
type statscompanion_service, system_server_service, service_manager_type;
type statsmanager_service, system_api_service, system_server_service, service_manager_type;
type uce_service, service_manager_type;
+type testservverfirst_service, service_manager_type;
diff --git a/private/service_contexts b/private/service_contexts
index 7c9f396..c1687f7 100755
--- a/private/service_contexts
+++ b/private/service_contexts
@@ -249,3 +249,4 @@
window u:object_r:window_service:s0
glasses u:object_r:sim_glasses_service:s0
* u:object_r:default_android_service:s0
+TestService u:object_r:testservverfirst_service:s0
diff --git a/private/untrusted_app.te b/private/untrusted_app.te
index 6e7a99c..97a84e3 100644
--- a/private/untrusted_app.te
+++ b/private/untrusted_app.te
@@ -14,3 +14,5 @@
untrusted_app_domain(untrusted_app)
net_domain(untrusted_app)
bluetooth_domain(untrusted_app)
+allow untrusted_app testservverfirst:binder { transfer call };
+allow untrusted_app testservverfirst_service:service_manager find;