主要分享在Android9.0上添加自定义服务的过程,和遇到的SELinux权限的问题,这篇帖子将紧接着上一篇Android系统源码编译,接下来还是以Android9.0,手机设备Piexl一代为例,来讲述framework自定义系统服务。
一、环境准备
(1) Ubuntu16.04(270G+16核+32GRAM)
(2) VMware15
(3) Android Studio (可以在这里创建一个工程,把类写好后拷贝到Android系统源码下)
(4) Sublim Text 3 (这个工具用于修改Android源代码,装好ctags插件实现函数之间的跳转)
二、概述
自定义系统服务首先要创建aidl文件、aidl的stub实现类以及服务的Manager类,总共涉及到三个文件(这里我会进行一个拓展,如何在系统服务中添加一个回调,那么现在总共涉及到四个文件)首先我们先定义文件的名称:
(1)IHelloService.aidl
(2)HelloService.java
(3)HelloServiceManager.java
(4)IHelloCallback.aidl (回调接口,主要用于做一些监听事件,在某些场景下很有用,比如说监听某些函数的调用或者返回一些有用的数据)
/frameworks/base/core/java/android/os/IHelloCallback.aidl
package android.os;
// Declare any non-default types here with import statements
interface IHelloCallback{
void callback(String str);
}
/frameworks/base/core/java/android/os/IHelloService.aidl
package android.os;
import android.os.IHelloCallback;
// Declare any non-default types here with import statements
interface IHelloService{
void registerCallBack(IHelloCallback callBack);
void registerCallBack(IHelloCallback callBack);
void invokeHello(String str);
}
/frameworks/base/core/java/com/android/server/HelloService.java
package com.android.server;
import android.os.IHelloCallback;
import android.os.IHelloService;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
public class HelloService extends IHelloService.Stub {
private RemoteCallbackList<IHelloCallback> sCallbackList = new RemoteCallbackList();
@Override
void registerCallBack(IHelloCallback callback) throws RemoteException{
if(callback != null) {
sCallbackList.register(callback);
}
}
@Override
void registerCallBack(IHelloCallback callback) throws RemoteException{
if(callback != null) {
sCallbackList.unregister(callback);
}
}
@Override
void invokeHello(String str) throws RemoteException{
/*
注意这里有一个坑,就是RemoteCallbackList的beginBroadcast方法
和finishBroadcast方法必须要配套使用否则会抛出异常;
解决方案可以进行加锁,或者使用单个线程来控制调用
*/
int len = sRemoteCallbackList.beginBroadcast();
for (int i=0;i<len;i++) {
try {
IHelloCallback callback= sRemoteCallbackList.getBroadcastItem(i);
callback.callback(str);
}catch (Exception e) {
e.printStackTrace();
}
}
sRemoteCallbackList.finishBroadcast();
}
}
/frameworks/base/core/java/com/android/server/HelloServiceManager.java
package com.android.server;
import android.content.Context;
import android.os.IHelloCallback;
import android.os.IHelloService;
import android.os.RemoteException;
public class HelloServiceManager {
private Context context;
private IHelloService helloService;
public HelloServiceManager(Context context, IHelloService helloService) {
this.context = context;
this.helloService = helloService;
}
public void registerCallBack (IHelloCallback callback) throws RemoteException {
helloService.registerCallBack(callback);
}
public void unRegisterCallBack(IHelloCallback callback) throws RemoteException {
helloService.unRegisterCallBack(callback);
}
public void invokeApi(String str) {
try {
helloService.invokeHello(str);
}catch (Exception e) {
e.printStackTrace();
}
}
}
三、注册系统服务
(1)在/frameworks/base/core/java/android/content/Context.java
文件中添加属性
public static final String HELLO_SERVICE = "hello";
.....
.....
.....
@StringDef(suffix = { "_SERVICE" }, value = {
....
....
HELLO_SERVICE, //在这里添加系统服务的静态字段
....
....
})
(2)在/frameworks/base/services/java/com/android/server/SystemServer.java
文件中的startOtherServices
方法中添加系统服务
try{
//.................
traceBeginAndSlog("HelloService");
HelloService helloService = new HelloService();
ServiceManager.addService(Context.HELLO_SERVICE, helloService);
traceEnd();
}catch(Exception e){
//................
//................
}
(3)在/frameworks/base/core/java/android/app/SystemServiceRegistry.java
文件中的static静态代码块
中注册系统服务
static {
//.....................
registerService(Context.HELLO_SERVICE, HelloServiceManager.class,
new CachedServiceFetcher<HelloServiceManager>() {
@Override
public HelloServiceManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
IHelloService service = IHelloService.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.HELLO_SERVICE));
return new HelloServiceManager(ctx.getOuterContext(), service);
}});
}
三、注册aidl文件
编辑\aosp\frameworks\base\Android.dp
文件,添加以下内容
"core/java/android/os/IHelloService.aidl",
"core/java/android/os/IHelloCallback.aidl",
四、添加SELinux权限
这里涉及的文件比较多,按照步骤一步一步添加就可以了
(1)编辑
a. system/sepolicy/private/service_contexts
文件
b. system/sepolicy/prebuilts/api/28.0/private/service_contexts
文件
c. system/sepolicy/prebuilts/api/27.0/private/service_contexts
文件
d. system/sepolicy/prebuilts/api/26.0/private/service_contexts
文件
添加内容如下(注意这文件内容要一致,要不然编译通不过):
hello u:object_r:hello_service:s0
(2)编辑
a. system/sepolicy/public/service.te
文件
b. system/sepolicy/prebuilts/api/28.0/public/service.te
文件
c. system/sepolicy/prebuilts/api/27.0/public/service.te
文件
d. system/sepolicy/prebuilts/api/26.0/public/service.te
文件
添加内容如下(注意这文件内容要一致,要不然编译通不过):
type hello_service, system_api_service, system_server_service, service_manager_type;
(3)编辑
a. system/sepolicy/private/compat/26.0/26.0.cil
文件,
b. system/sepolicy/prebuilts/api/28.0/private/compat/26.0/26.0.cil
文件
c. system/sepolicy/prebuilts/api/27.0/private/compat/26.0/26.0.cil
文件
(typeattributeset hello_service_26_0 (hello_service))
(4)编辑
a. system/sepolicy/private/compat/27.0/27.0.cil
文件
b. system/sepolicy/prebuilts/api/28.0/private/compat/27.0/27.0.cil
文件
(typeattributeset hello_service_27_0 (hello_service))
(5)编辑 system/sepolicy/prebuilts/api/26.0/nonplat_sepolicy.cil
文件
(typeattribute hello_service_26_0)
(roletype object_r hello_service_26_0)
(6)编辑system/sepolicy/prebuilts/api/27.0/nonplat_sepolicy.cil
文件
(typeattribute hello_service_27_0)
(roletype object_r hello_service_27_0)
(7)编辑
a. system/sepolicy/private/untrusted_app
文件
b. system/sepolicy/prebuilts/api/28.0/private/untrusted_app
文件
c. system/sepolicy/prebuilts/api/27.0/private/untrusted_app
文件
d.system/sepolicy/prebuilts/api/26.0/private/untrusted_app
文件
allow untrusted_app hello_service:service_manager find;
(8)编辑
a. system/sepolicy/private/untrusted_app_25
文件
b. system/sepolicy/prebuilts/api/28.0/private/untrusted_app_25
文件
c. system/sepolicy/prebuilts/api/27.0/private/untrusted_app_25
文件
d.system/sepolicy/prebuilts/api/26.0/private/untrusted_app_25
文件
allow untrusted_app_25 hello_service:service_manager find;
(9)编辑
a. system/sepolicy/private/untrusted_app_27
文件
b. system/sepolicy/prebuilts/api/28.0/private/untrusted_app_27
文件
c. system/sepolicy/prebuilts/api/27.0/private/untrusted_app_27
文件
d.system/sepolicy/prebuilts/api/26.0/private/untrusted_app_27
文件
allow untrusted_app_27 hello_service:service_manager find;
(10)编辑
a. system/sepolicy/private/untrusted_app_all
文件
b. system/sepolicy/prebuilts/api/28.0/private/untrusted_app_all
文件
c. system/sepolicy/prebuilts/api/27.0/private/untrusted_app_all
文件
d.system/sepolicy/prebuilts/api/26.0/private/untrusted_app_all
文件
allow untrusted_app_all hello_service:service_manager find;
(11)编辑
a. system/sepolicy/private/untrusted_v2_app
文件
b. system/sepolicy/prebuilts/api/28.0/private/untrusted_v2_app
文件
c. system/sepolicy/prebuilts/api/27.0/private/untrusted_v2_app
文件
d.system/sepolicy/prebuilts/api/26.0/private/untrusted_v2_app
文件
allow untrusted_v2_app hello_service:service_manager find;
添加完之后,使用make update-api
更新
五、编译
在aosp根目录下使用以下命令进行编译
(1)source build/envsetup.sh
(2)lunch
(3)make -j32
六、调用自定义服务
在这里可以利用java的双亲委派机制,在自己的工程中引入这些自定义服务相关联的类,这样就可以直接使用这些类了,不需要用到反射
HelloServiceManager helloServiceManager = (HelloServiceManager) getSystemService(Context.HELLO_SERVICE);
helloServiceManager.registerCallBack(new IHelloCallback(){
public void callback(String str){
Log.e("asjhan","接收到的内容:"+str);
}
});
helloServiceManager.invokeApi("hello world");
七、编译报错
编译报错最多的就是SELinux方面的东西,这里举几个常见的报错例子
(1)find权限
SELinux: avc: denied { find } for service=hello pid=5620 uid=10073 scontext=u:r:untrusted_app:s0:c73,c256,c512,c768 tcontext=u:object_r:hello_service:s0 tclass=service_manager permissive=0
解决方式
allow untrusted_app hello_service:service_manager find
基本的参考公式,模板:allow scontext tcontext:tclass permission;
scontext=u:r:untrusted_app 什么文件
tcontext=u:object_r:hello_service 什么服务
tclass=service_manager 什么类型
denied { find } 什么权限
(2)api更新
frameworks/base/api/system-current.txt:25036: error 8: Removed public class
解决方式
make update-api
如果修改了Android原有API的 ,需要update frameworks/base/api/current.txt。否则编译被中断并出现编译错误提示
asjhan for Android reverse