06 Android系统之添加java层系统服务
引入概念
目前对android系统体系了解比较少,主要区分一下服务、系统服务这两个概念
- Android服务是一个后台运行的组件,执行长时间运行且不需要用户交互的任务。在android开发中作为一个
应用组件,通过继承类extern Service来使用。 - Android系统服务。理解为随着andorid系统启动运行的service,分为
本地守护进程、Native系统服务和Java系统服务。 
有相同点更有不同点,但请不要把两个概念弄混淆了!!!
 然后下面记录一下添加自定义一个java系统服务的步骤,参考于qiushao大神的blog。基于android-10版本的AOSP源码,
添加服务
1、 定义服务接口
 首先我们得定义我们的服务名是什么,提供什么样的接口。在frameworks/base/core/java/android目录下添加pure文件夹
$ tree frameworks/base/core/java/android/pure
frameworks/base/core/java/android/pure
└── IHelloService.aidl     # 使用 aidl 定义服务接口
0 directories, 1 file
  
 - 1
 - 2
 - 3
 - 4
 - 5
 
定义接口文件IHelloService.aidl,模块名IHelloService,接口hello将实现播放指定路径的音频文件
package android.pure;
interface IHelloService {
    void hello(String name);
}
  
 - 1
 - 2
 - 3
 - 4
 - 5
 
frameworks/base/Android.bp文件中找到模块名framework-defaults,添加
"core/java/android/pure/IHelloService.aidl",
  
 - 1
 
此时,进入 framework/base 目录执行 mm -j 命令编译 framework.jar 模块。
 编译成功后,会在 out/soong/.intermediates/frameworks/base/framework/android_common/gen/aidl/frameworks/base/core/java/android/pure 目录生成 IHelloService.java 这个文件
2、 实现接口
 然后在frameworks/base/services/core/java/com/android/server下创建HelloService.java文件(接口实现) 内容如下
package com.android.server;
import android.pure.IHelloService;
import android.util.Log;
public class HelloService extends IHelloService.Stub {
    private final String TAG = "HelloService";
    public HelloService() {
        Log.d(TAG, "create hello service");
    }
    @Override
    public void hello(String name) {
        Log.d(TAG, "hello " + name);
    }
}
  
 - 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 
3、 将服务添加到 ServiceManager
 修改 frameworks/base/services/java/com/android/server/SystemServer.java 文件,在startOtherServices方法里面增加以下代码
// add hello service
traceBeginAndSlog("HelloService");
ServiceManager.addService("HelloService", new HelloService());
traceEnd();
  
 - 1
 - 2
 - 3
 - 4
 
4、 编译验证 & 系统无法启动
 现在已经实现的HelloService接口模块,并添加到ServiceManager。开始尝试整编下android源码
$ source ./build/envsetup.sh   # 导出环境变量(之前执行过了)
$ lunch product01-eng          # 选择Product
$ make api-stubs-docs-update-current-api -j4            # 更新api接口
$ make -j4 						# 编译
  
 - 1
 - 2
 - 3
 - 4
 
然后启动emulator虚拟机,发现一直停留在logo界面,说明系统没起来。。这时候可以adb调试,我们查看一下log记录
$ emulator 			# 发现android系统界面没起来
...
...
$ adb shell logcat -b all > logSystem.txt    # 抓取android层的 log
...
^C
  
 - 1
 - 2
 - 3
 - 4
 - 5
 - 6
 
日志中检索我们想要的关键字HelloService,发现
04-02 01:24:25.871  2224  2224 I SystemServer: HelloService
04-02 01:24:25.871  1528  1528 I auditd  : avc:  denied  { add } for service=HelloService pid=2224 uid=1000 scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0
04-02 01:24:25.871  2224  2224 E System  : ******************************************
04-02 01:24:25.871  2224  2224 E System  : ************ Failure starting system services
04-02 01:24:25.871  2224  2224 E System  : java.lang.SecurityException
04-02 01:24:25.871  2224  2224 E System  : 	at android.os.BinderProxy.transactNative(Native Method)
04-02 01:24:25.871  2224  2224 E System  : 	at android.os.BinderProxy.transact(BinderProxy.java:510)
04-02 01:24:25.871  2224  2224 E System  : 	at android.os.ServiceManagerProxy.addService(ServiceManagerNative.java:156)
04-02 01:24:25.871  2224  2224 E System  : 	at android.os.ServiceManager.addService(ServiceManager.java:192)
04-02 01:24:25.871  2224  2224 E System  : 	at android.os.ServiceManager.addService(ServiceManager.java:161)
04-02 01:24:25.871  2224  2224 E System  : 	at com.android.server.SystemServer.startOtherServices(SystemServer.java:920)
04-02 01:24:25.871  2224  2224 E System  : 	at com.android.server.SystemServer.run(SystemServer.java:512)
04-02 01:24:25.871  2224  2224 E System  : 	at com.android.server.SystemServer.main(SystemServer.java:349)
04-02 01:24:25.871  2224  2224 E System  : 	at java.lang.reflect.Method.invoke(Native Method)
04-02 01:24:25.871  2224  2224 E System  : 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
04-02 01:24:25.871  2224  2224 E System  : 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:908)
04-02 01:24:25.871  2224  2224 D SystemServerTiming: HelloService took to complete: 1ms
04-02 01:24:25.871  2224  2224 E AndroidRuntime: *** FATAL EXCEPTION IN SYSTEM PROCESS: main
  
 - 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 
然后定位到这一句04-02 01:24:25.871 1528 1528 I auditd : avc: denied { add } for service=HelloService pid=2224 uid=1000 scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0,不理解没关系,google一下。发现是selinux方面的原因。
为了进一步验证猜想,将系统中的selinux关掉试试。通过setenforce 0命令,重启系统发现正常了,印证了之前的猜想,确实selinux配置的原因。
$ adb shell setenforce 0   # 禁用selinux
$ emulator -wipe-data      # 擦掉data区,重启系统
  
 - 1
 - 2
 - 3
 - 4
 
5、 设置selinux规则
 然后我们只需要添加这个自定义服务HelloService相关的 SELinux 规则。为了方便之后验证,打开selinux
$ adb shell setenforce 1   # 打开selinux
  
 - 1
 
Android 10 的 selinux 规则是放在 system/sepolicy 目录下的。不怎么了解SELinux规则,可以参考现有的系统服务的规则去添加,这里参考的是 network_time_update_service 服务。
$ cd system/sepolicy    # selinux规则在这个目录
$ grep -nr network_time_update_service   # 查找network_time_update_service服务相关的selinux配置
  
 - 1
 - 2
 
涉及到的文件很多,有部分文件是不需要修改的,我们先把找到的所有 service.te 和 service_contexts 都参考 network_time_update_service 加上 HelloService 的配置。
$ find -name service.te
./prebuilts/api/27.0/public/service.te   # 需要
./prebuilts/api/28.0/public/service.te   # 需要
./prebuilts/api/28.0/private/service.te
./prebuilts/api/29.0/public/service.te    # 需要
./prebuilts/api/29.0/private/service.te
./prebuilts/api/26.0/public/service.te   # 需要
./public/service.te                 # 需要
./private/service.te
$ find -name service_contexts
./reqd_mask/service_contexts
./prebuilts/api/27.0/private/service_contexts   # 需要
./prebuilts/api/28.0/private/service_contexts   # 需要
./prebuilts/api/29.0/private/service_contexts       # 需要
./prebuilts/api/26.0/private/service_contexts   # 需要
./private/service_contexts         # 需要
  
 - 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 
其中
service_contexts上添加HelloService u:object_r:HelloService:s0;service.te上添加type HelloService, system_server_service, service_manager_type;。
6、 编译验证
 最后再次编译一遍,启动届满没有什么问题了。adb进入系统查看一下有没有这个服务
$ source ./build/envsetup.sh   # 导出环境变量(之前执行过了)
$ lunch product01-eng          # 选择Product
$ make api-stubs-docs-update-current-api -j4            # 更新api接口
$ make -j4 						# 编译
....
....
$ adb shell
pure:/ # service list | grep HelloService                                                                                                                                                               
16      HelloService: [android.pure.IHelloService]
pure:/ #
  
 - 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 
错误记录
1、 添加服务后,make -j4编译系统报错
error: Added package android.pure [AddedPackage]
Aborting: Found compatibility problems checking the public API against the API in /home/mi/source/android-10/frameworks/base/api/current.txt
-e 
******************************
You have tried to change the API from what has been previously approved.
To make these errors go away, you have two choices:
   1. You can add '@hide' javadoc comments to the methods, etc. listed in the
      errors above.
   2. You can update current.txt by executing the following command:
         make api-stubs-docs-update-current-api
      To submit the revised current.txt to the main Android repository,
      you will need approval.
******************************
09:05:24 ninja failed with: exit status 1
#### failed to build some targets (06:37 (mm:ss)) ####
  
 - 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 
解决思路: 没有更新服务接口,编译前执行make api-stubs-docs-update-current-api -j4
2、添加selinux后,编译报错
SELinux: The following public types were found added to the policy without an entry into the compatibility mapping file(s) found in private/compat/V.v/V.v[.ignore].cil, where V.v is the latest API level.
HelloService
See examples of how to fix this:
https://android-review.git.corp.google.com/c/platform/system/sepolicy/+/781036
https://android-review.git.corp.google.com/c/platform/system/sepolicy/+/852612
[ 20% 5/24] build out/target/product/pure/obj/ETC/treble_sepolicy_tests_28.0_intermediates/treble_sepolicy_tests_28.0
FAILED: out/target/product/pure/obj/ETC/treble_sepolicy_tests_28.0_intermediates/treble_sepolicy_tests_28.0
/bin/bash -c "(out/host/linux-x86/bin/treble_sepolicy_tests -l    out/host/linux-x86/lib64/libsepolwrap.so  -f out/target/product/pure/obj/ETC/plat_file_contexts_intermediates/plat_file_contexts  -f out/target/product/pure/obj/ETC/vendor_file_contexts_intermediates/vendor_file_contexts    -b out/target/product/pure/obj/ETC/built_plat_sepolicy_intermediates/built_plat_sepolicy -m out/target/product/pure/obj/ETC/treble_sepolicy_tests_28.0_intermediates/28.0_mapping.combined.cil    -o out/target/product/pure/obj/ETC/treble_sepolicy_tests_28.0_intermediates/built_28.0_plat_sepolicy -p out/target/product/pure/obj/ETC/sepolicy_intermediates/sepolicy     -u out/target/product/pure/obj/ETC/built_plat_sepolicy_intermediates/base_plat_pub_policy.cil     --fake-treble ) && (touch out/target/product/pure/obj/ETC/treble_sepolicy_tests_28.0_intermediates/treble_sepolicy_tests_28.0 )"
SELinux: The following public types were found added to the policy without an entry into the compatibility mapping file(s) found in private/compat/V.v/V.v[.ignore].cil, where V.v is the latest API level.
HelloService
See examples of how to fix this:
https://android-review.git.corp.google.com/c/platform/system/sepolicy/+/781036
https://android-review.git.corp.google.com/c/platform/system/sepolicy/+/852612
21:45:48 ninja failed with: exit status 1
#### failed to build some targets (16 seconds) ####
  
 - 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 
解决思路: selinux没配置好,没有将配置覆盖所有需要的te文件。检查本地配置,按照上面的方法,在配置一下。
3、启动emulator之后,系统没起来,同时log报错
hinzer@ubuntu:android-10$ emulator -wipe-data
emulator: WARNING: Couldn't find crash service executable /home/hinzer/source/android-10/prebuilts/android-emulator/linux-x86_64/emulator64-crash-service
emulator: WARNING: system partition size adjusted to match image file (3083 MB > 800 MB)
qemu_ram_alloc_user_backed: call
context mismatch in svga_surface_destroy   # 这个错误
....
  
 - 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 
解决方法: 通过网络查询到解决方法,由于我这边是VM上运行Ubuntu虚拟机,然后在跑emulator。我需要把VM设置中的显示器中的图形渲染关闭,这一操作需要关闭虚拟机,重启后在运行emulator 验证就没有问题了。
小结
- 查看日志 使用
logcat -b all,不清楚不要过滤处理,查看全部log - 不确定的情况下,可以系统上直接启动/禁止
selinux验证猜想,然后进一步调试 
参考资料
文章来源: blog.csdn.net,作者:hinzer,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/feit2417/article/details/105279290
- 点赞
 - 收藏
 - 关注作者
 
            
           
评论(0)