android添加自定义的系统服务

前言

其本质,还是通过binder方式进行通信。

  1. 创建一个binder接口,可通过aidl方式
  2. 创建接口的实现类,即为服务类
  3. 添加服务到系统
  4. 创建service管理类manage
  5. 注册服务对应的manger,以供调用者使用
  6. 配置修改SELinux权限。(在Enforcing强制模式下,无法使用)
  7. 编译,需先make update-api
步骤

一个Map service的例子,只实现简单的set和get方法。

PS:在操作的时候,有一个小技巧,就是查看现有熟悉的服务的写法,比如IAlarmManager.aidlIPackageManager.aidlIWifiManager.aidl等等。

1、定义aidl文件

首先,在源码frameworks/base/core/java/android/os/下创建aidl文件

//@@@	frameworks/base/core/java/android/os/
package android.os;https://blog.csdn.net/qq_28827333/article/details/89455820
/**
 * @hide
 */
interface IMapService {
     void putValue(String key, String value);
     String getValue(String key);
}

然后,添加该aidl文件路径到mk/bp中,以供系统编译,才能生成相应的java接口文件

#@@@	frameworks/base/Android.bp(老版本在Android.mk中)
...
java_library {san
...
"core/java/android/os/IMapService.aidl",
...
}
...

最后,我们简单说一下,通过aidl生成的java接口,该接口包含了俩部分:

1、静态内部抽象类Stub,该抽象类继承Binder

2、声明了具体的功能的抽象方法(aidl文件中声明的方法)

2、实现aidl接口

该service为上述接口的实现类。继承了接口中的binder匿名类,并实现我们aidl中声明的方法。

//@@@	frameworks/base/services/core/java/com/android/server/ 
package com.android.server;

import android.content.Context;
import android.os.RemoteException;
import android.os.IMapService;
import java.util.HashMap;

public class MapService extends IMapService.Stub {
    private static HashMap<String, String> map = new HashMap<>();

     @Override
     public void putValue(String key, String value) throws RemoteException {
        map.put(key, value);
     }

     @Override
     public String getValue(String key) throws RemoteException {
        return map.get(key);
     }
}

3、添加新服务

首先,定义新服务的name

//@@@	frameworks/base/core/java/android/content/Context.java`
public abstract class Context {
	...	
	public static final String MAP_SERVICE = "mapmanager";
}

然后,将新service加入到ServiceManager

//@@@	frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
	...
    try {
        traceBeginAndSlog("StartMapService");
        Slog.i(TAG,"MapService");
        ServiceManager.addService(Context.MAP_SERVICE, new MapService());
        traceEnd();
    }catch (Exception e) {
        e.printStackTrace();
    }
    ...
}

4、创建新服务的管理类

创建新服务的管类。通过该管理类将service封装起来,方便调用者操作

//@@@	core/java/android/app/
package android.app;
import android.os.IMapService;

public class MapServiceManager {
    private IMapService mIMapService;
    
    public MapServiceManager(IMapService service){
    	mIMapService = service;
    }
    
    public void getValue(String key){
        try {
            mIMapService.getValue(key);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public void setValue(String key, String value){
        try {
            mIMapService.putValue(key, value);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

5、注册服务

注册后,我们可以通过getSystemService(服务名称)来获取到管理类对象。这块的注册逻辑,是通过map将名称和类以及回调函数绑定的,具体可以看源码。

//@@@	/frameworks/base/core/java/android/app/SystemServiceRegistry.java
public final class SystemServiceRegistry {
    ...
	...
    registerService(Context.MAP_SERVICE, MapServiceManager.class,
        new CachedServiceFetcher<MapServiceManager>() {
            @Override
            public MapServiceManager createService(ContextImpl ctx) {
                //通过服务名称获取其binder
                IBinder b = ServiceManager.getService(Context.MAP_SERVICE);            
                //将binder转为接口对象,传递给manager管理
                IMapService service = IMapService.Stub.asInterface(b);                        
                return new MapServiceManager(service);
            }});
    ...
	...
}

6、配置修改SELinux权限

在高版本,需要配置SELinux权限,否则处于SELinux的Enforcing强制模式下,服务无法被使用

  • 添加服务类型
#@@@ /device/xxxx/service.te 末尾添加
type map_service, 			app_api_service, system_api_service, service_manager_type;
  • 对服务添加权限
#@@@ /device/xxxx/service_contexts 末尾添加
mapmanager                  u:object_r:map_service:s0
  • 如若还报错,可按以下方式修改

//报错:
SELinux: avc: denied { find } for service=mapmanager pid=2305 uid=10063 scontext=u:r:untrusted_app:s0:c63,c256,c512,c768 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0

//解释:

  • 缺少什么权限:{find}

  • 谁缺少权限: u:r:untrusted_app:s0:c63,c256,c512,c768

  • 对哪个文件缺少权限:tcontext=u:object_r:default_android_service:s0

  • 什么类型的文件:tclass=service_manage

完整说明:untrusted_app进程对default_android_service类型service_manage的缺少find权限。

//解决方法:

在untrusted_app.te文件中,添加权限

allow untrusted_app default_android_service:service_manager find
//allow untrusted_app default_android_service:service_manager {find write open}

SEAndroid app分类:

  • untrusted_app: 第三方app,没有Android平台签名,没有system权限

  • platform_app: 有android平台签名,没有system权限

  • system_app: 有android平台签名和system权限

7、编译

  1. make update-api -j8 //更新api
  2. make -j8 //编rom
  3. 刷机,重启

8、验证

打开android stuido,创建一个项目

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MapServiceManager manager = (MapServiceManager) getSystemService("mapservice");
        manager.setValue("hellow", "world");
        Log.d("MapServiceManager", manager.getValue("hellow") + "");
    }

如果没有导入新服务,此处不会识别MapServiceManager,我们可以在本项目中创建一个MapServiceManager.java的影子文件,包名必须为android.app

//@@@	XXXX/app/src/main/java/android/app/MapServiceManager.java
package android.app;

public class MapServiceManager {

    public String getValue(String key){
        return null;
    }

    public void setValue(String key, String value){
        
    }
}
参考

参考一 、参考二、参考三

你可能感兴趣的:(Android基础,Android)