其本质,还是通过binder方式进行通信。
一个Map service的例子,只实现简单的set和get方法。
PS:在操作的时候,有一个小技巧,就是查看现有熟悉的服务的写法,比如IAlarmManager.aidl
、IPackageManager.aidl
、IWifiManager.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、编译
- make update-api -j8 //更新api
- make -j8 //编rom
- 刷机,重启
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){
}
}
参考一 、参考二、参考三