Service的注册
具体流程不细说了,核心代码在SystemServer的内部类ServerThread.run方法中.
基本所有Java层的Service都会在这里被调用或者初始化,并通过ServiceManager.addService()纳入管理。如下图:
try {
Slog.i(TAG, "Ethernet Service");
ethernet = new EthernetService(context);
ServiceManager.addService(Context.ETHERNET_SERVICE, ethernet);
} catch (Throwable e) {
reportWtf("starting ETHERNET Service", e);
}
EthernetService也是相比Android原生新增的Service,可供参考。
Manager的调用
Service在上层的代言人就是对应的Manager。通过Context.getSystemService(name)获取Manager实例。而Manager的实例,是在ContextImpl类初始化的时候,就会生成。如下图:
static {
registerService(ACCESSIBILITY_SERVICE, new ServiceFetcher() {
public Object getService(ContextImpl ctx) {
return AccessibilityManager.getInstance(ctx);
}});
registerService(ACCOUNT_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);
IAccountManager service = IAccountManager.Stub.asInterface(b);
return new AccountManager(ctx, service);
}});
registerService(ACTIVITY_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
}});
通过ContextImpl.registerService()方法,会将Service Name与封装了Manager实例的ServiceFetcher存储到Map集合中供应用获取调用。如下图:
private static void registerService(String serviceName, ServiceFetcher fetcher) {
if (!(fetcher instanceof StaticServiceFetcher)) {
fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;
}
SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
}
@Override
public Object getSystemService(String name) {
ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
return fetcher == null ? null : fetcher.getService(this);
}
Service与Manager的交互
上面说了,Manager就是Service在上层的代言人。除了Manager中定义的常用功能,如果用到Service的时候,就可以让Service来完成。而Manager又是怎么指挥Service工作呢?
要指挥Service工作,首先要有Service对象。而Service对象工作在system_server进程中,所以Android就提供了Binder机制,来进行IPC访问。既然是跨进程通信,自然需要有一个规范。那就是AIDL。参考:http://developer.android.com/guide/components/aidl.html
ServiceDemo工程举例
IDemoManager.aidl中定义了需要DemoService来完成的功能,,它会在Eclipse中会自动编译出IDemoManager.java文件到gen目录下。其实也是调用的sdk中platform-tools中的aidl工具,进行转换。源码环境make,同样如此。
然后在定义DemoService的时候,继承IDemoManager.Stub,实现抽象方法,其实也就是需要Service来实现的方法。这个过程中,aidl生成的IDemoManager.java文件中可以看到通过Binder进行通信的实现。通过aidl这个技术,在DemoManager中获取到DemoService对象进行工作。
新增系统Service
1:定义Manager
在ContextImpl的static代码块中registerService。如果需要,可在定义一个常量字段声明Service name。
2:定义IManager.aidl
与Manager.java放于同目录,并添加到Android.mk中。
3:定义Service
在SystemServer的ServerThread.run方法中,初始化Service到ServiceManager中.
拙见,关于Binder机制还有待研究。欢迎补充修改。