欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

06 Android系统之添加java层系统服务

程序员文章站 2024-02-02 22:11:10
...

引入概念

目前对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

定义接口文件IHelloService.aidl,模块名IHelloService,接口hello将实现播放指定路径的音频文件

package android.pure;
interface IHelloService {
    void hello(String name);
}

frameworks/base/Android.bp文件中找到模块名framework-defaults,添加

"core/java/android/pure/IHelloService.aidl",

此时,进入 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);
    }
}

3、 将服务添加到 ServiceManager
修改 frameworks/base/services/java/com/android/server/SystemServer.java 文件,在startOtherServices方法里面增加以下代码

// add hello service
traceBeginAndSlog("HelloService");
ServiceManager.addService("HelloService", new HelloService());
traceEnd();

4、 编译验证 & 系统无法启动
现在已经实现的HelloService接口模块,并添加到ServiceManager。开始尝试整编下android源码

$ source ./build/envsetup.sh   # 导出环境变量(之前执行过了)
$ lunch product01-eng          # 选择Product
$ make api-stubs-docs-update-current-api -j4            # 更新api接口
$ make -j4 						# 编译

然后启动emulator虚拟机,发现一直停留在logo界面,说明系统没起来。。这时候可以adb调试,我们查看一下log记录

$ emulator 			# 发现android系统界面没起来
...
...
$ adb shell logcat -b all > logSystem.txt    # 抓取android层的 log
...
^C

日志中检索我们想要的关键字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

然后定位到这一句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区,重启系统

5、 设置selinux规则
然后我们只需要添加这个自定义服务HelloService相关的 SELinux 规则。为了方便之后验证,打开selinux

$ adb shell setenforce 1   # 打开selinux

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配置

涉及到的文件很多,有部分文件是不需要修改的,我们先把找到的所有 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         # 需要

其中

  • 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、 添加服务后,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)) ####

解决思路: 没有更新服务接口,编译前执行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) ####

解决思路: selinux没配置好,没有将配置覆盖所有需要的te文件。检查本地配置,按照上面的方法,在配置一下。

3、启动emulator之后,系统没起来,同时log报错

[email protected]: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   # 这个错误
....

解决方法: 通过网络查询到解决方法,由于我这边是VM上运行Ubuntu虚拟机,然后在跑emulator。我需要把VM设置中的显示器中的图形渲染关闭,这一操作需要关闭虚拟机,重启后在运行emulator 验证就没有问题了。

小结

  • 查看日志 使用logcat -b all,不清楚不要过滤处理,查看全部log
  • 不确定的情况下,可以系统上直接启动/禁止selinux验证猜想,然后进一步调试

参考资料