1 引言
本文主要是记录自己在init.rc中添加开机启动service的流程,以及过程中遇到的问题和对应的解决方案,供大家参考
android版本:Android-9.0.0_r1
设备信息:Pixel XL
2 步骤
init.rc中添加service主要分为三步:
(1)源码中添加可执行文件;
(2)init.rc中添加service;
(3)解决sepolicy问题(如果出现的话),
以下分别进行记录。
2.1 源码目录中添加自己的可执行文件
此处写的简易一些,分为一个cpp文件及一个Android.mk文件
printTest.cpp:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
void my_system(const char *cmd)
{
char result[10240] = {0};
char buf[1024] = {0};
FILE *fp = NULL;
if( (fp = popen(cmd, "r")) == NULL ) {
printf("popen error!\n");
return;
}
while (fgets(buf, sizeof(buf), fp)) {
strcat(result, buf);
}
pclose(fp);
printf("result: %s\n", result);
}
int main()
{
printf("before running");
for(int i = 0; i < 100; i++) {
sleep(30);
my_system("ps -ef");
}
return 0;
}
Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
printTest.cpp
LOCAL_MODULE:= printTest
LOCAL_32_BIT_ONLY := true
include $(BUILD_EXECUTABLE)
另外,单独的添加这两个文件后,再执行make命令的话,是不会编译这个二进制文件的,还需要在build/target/product/base.mk下加上一句:PRODUCT_PACKAGES += printTest,如下:
diff --git a/target/product/base.mk b/target/product/base.mk
old mode 100644
new mode 100755
index bc3710c61..1d2eafd1e
--- a/target/product/base.mk
+++ b/target/product/base.mk
@@ -142,6 +142,7 @@ PRODUCT_PACKAGES += \
traced_probes \
vdc \
vold \
+ printTest \
wm
这样在执行make后,android会自动编译该二进制文件,在system/bin/ 文件夹下也会有printTest文件出现
2.2 init.rc文件添加自己的service
init.rc文件位置:system/core/rootdir/init.rc
添加方法是先用service语句定义自己的service名,再在合适的时机进行start(此处选择启动后进行start)
2.2.1 定义service
在init.rc中添加下列语句(此处均为printTest,相应名称需要按照自己的名字进行替换)
service printTest /system/bin/printTest
user root
group root
seclabel u:r:printTest:s0
class main
oneshot
2.2.2 设置启动时机
service语句只是定义了一个service,还需要在相应的时候进行启动,这里选的是在on property:sys.boot_completed=1下一行添加start printTest语句:
diff --git a/rootdir/init.rc b/rootdir/init.rc
old mode 100644
new mode 100755
index b9464e7fd..2fcb24f6f
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -717,6 +717,7 @@ on property:vold.decrypt=trigger_shutdown_framework
class_reset main
on property:sys.boot_completed=1
+ start printTest
bootchart stop
这样,在启动完成后,就会开始执行该service(路径为/system/bin/printTest)
3 sepolicy策略
大多数的教程说在上述步骤完成后进行make及烧录,在adb中执行ps -Z理论上就可以看到自己的进程名,但android9则没有出现想要的结果。查找对应的文档,说该问题属于sepolicy策略问题,经过大量的尝试,将android9适用的方法给出:
3.1 /device/google/marlin/sepolicy/file_contexts
diff --git a/sepolicy/file_contexts b/sepolicy/file_contexts
old mode 100644
new mode 100755
index f104cbb4..0cea3b50
--- a/sepolicy/file_contexts
+++ b/sepolicy/file_contexts
@@ -81,6 +81,7 @@
# files in /system
/system/bin/preloads_copy\.sh u:object_r:preloads_copy_exec:s0
/system/bin/move_widevine_data\.sh u:object_r:move-widevine-data-sh_exec:s0
+/system/bin/printTest u:object_r:printTest_exec:s0
# files in /vendor
/vendor/bin/qsee_logger u:object_r:qsee_logger_exec:s0
3.2 file_contexts同目录下添加printTest.te文件
文件内容如下
type printTest, domain;
type printTest_exec, exec_type, file_type;
init_daemon_domain(printTest)
3.3修改domain.te
此时进行make编译,将会报如下错误
libsepol.report_failure: neverallow on line 998 of system/sepolicy/public/domain.te (or line 11313 of policy.conf) violated by allow printTest printTest_exec:file { execute entrypoint };
按照指示,翻到domain.te的998行,有如下内容:
full_treble_only(`
# Do not allow vendor components to execute files from system
# except for the ones whitelist here.
neverallow {
domain
-coredomain
-appdomain
-vendor_executes_system_violators
-vendor_init
} {
exec_type
-vendor_file_type
-crash_dump_exec
-netutils_wrapper_exec
}:file { entrypoint execute execute_no_trans };
')
参考其他人的博客,neverallow中带有“-”号的表明将该类型从neverallow规则中去除,按照报错信息,由于printTest和printTest_exec分别为domain及exec_type类型,所以在exec_type前加上-号,再次进行编译,报错:
The following domain(s) must be associated with the "coredomain" attribute because they are executed off of /system:
printTest
按照提示,将printTest.te修改如下
type printTest, domain, coredomain;
type printTest_exec, exec_type, file_type;
init_daemon_domain(printTest)
再进行make,无报错完成