读书人

Service与Android系统设计(九)

发布时间: 2012-11-05 09:35:12 作者: rapoo

Service与Android系统设计(9)

特别声明:本系列文章LiAnLab.org著作权所有,转载请注明出处。作者系LiAnLab.org资深Android技术顾问吴赫老师。本系列文章交流与讨论:@宋宝华Barry

3.5 System Service的驱动形式 --- ServiceManager

对于ServiceManager的使用,我们在应用程序编程时也会经常使用到,比如我们需要使用Sensor时,我们一般会做如下的调用:

mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

mSensorManager.registerListener(this, mAccelerometer,SensorManager.SENSOR_DELAY_UI);

@Override

public void onSensorChanged(SensorEvent event) {

if(event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)

return;

...

}

这样的编程模式,API说明会告诉我们,每次系统里加速度计Sensor发生状态变化时,就会触发onSensorChanged()回调方法被执行来处理Sensor的变动信息。这里就很好地说明了在系统范围内使用Service的另一种模式,就是通过getSystemService(),取回一个System Service的引用实例,然后便可以调用Service实现的方法,比如我们例子里的mSensorManager.registerListener()方法。

我们可以继承跟踪代码的实现,getSystemService()也并没有什么神奇的,它本质上只是创建一个Service列表的Cache而已,把ContextImpl.java与getSystemService()相关的实现抽出来,于是我们可以得到:

class ContextImpl extends Context {

...

static class ServiceFetcher { 4

int mContextCacheIndex = -1;

public Object getService(ContextImpl ctx) { 5

ArrayList<Object> cache = ctx.mServiceCache;

Object service;

synchronized (cache) {

if (cache.size() == 0) {

for (int i =0; i <sNextPerContextServiceCacheIndex; i++) {

cache.add(null);

}

} else {

service =cache.get(mContextCacheIndex);

if (service != null) {

return service;

}

}

service = createService(ctx);

cache.set(mContextCacheIndex,service);

return service;

}

}

public Object createService(ContextImpl ctx) { 6

throw new RuntimeException("Notimplemented");

}

}

private staticfinalHashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP =

new HashMap<String,ServiceFetcher>(); 2

private staticintsNextPerContextServiceCacheIndex =0;

private staticvoidregisterService(String serviceName, ServiceFetcher fetcher) { 3

if(!(fetcher instanceof StaticServiceFetcher)) {

fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;

}

SYSTEM_SERVICE_MAP.put(serviceName, fetcher);

}

static {

registerService(ACCESSIBILITY_SERVICE, new ServiceFetcher() { 7

public Object getService(ContextImpl ctx) {

returnAccessibilityManager.getInstance(ctx);

}});

registerService(ACTIVITY_SERVICE, new ServiceFetcher() { 8

public Object createService(ContextImpl ctx) {

return newActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());

}});

registerService(ALARM_SERVICE, new StaticServiceFetcher() { 9

public Object createStaticService() {

IBinder b = ServiceManager.getService(ALARM_SERVICE);

IAlarmManager service =IAlarmManager.Stub.asInterface(b);

return new AlarmManager(service);

}});

...

}

@Override

public ObjectgetSystemService(String name) { 1

ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);

return fetcher == null ? null : fetcher.getService(this);

}

...

}}

1 getSystemService()的实现。所有通过继承Context类来创建自己的执行片段,都会调用getSystemService()来取得SystemService的引用。在这一方法里,就是通过SYSTEM_SERVICE_MAP来取得Service所对应的Proxy对象。

2 SYSTEM_SERVICE_MAP,也只不过是通过String标识出来的ServiceFetcher对象而已,为了加速查找,使用了HashMap模板。

3 在Context对象里,会通过registerService()方法,将ServiceFetcher对象填充到SYSTEM_SERVICE_MAP里。

4 ServiceFetcher类。这只是Context对象内,为了更好地组织Service而提供的一种中间类型,Service本身通过ServiceFetcher引用,于是可以灵活地替换其getService()或是createService()方法。

5 标准的getService()实现。在正常情况下,getService()只是从Cache中查找是否已经创建好所需要的Service对象,如果有则直接返回这一对象,如果没有,则创建所需要的Service对象,再返回。

6 标准的createService()实现。跟抽象类的实现类似,如果该ServiceFetcher上承载的Service没有覆盖createService()方法,则基本上可以认定是出错了,此抛出异常。所以ServiceFetcher在注册时,要么需要覆盖getService()方法,否则必须要覆盖更底层的createService()方法。

7 覆盖getService()方法。因为上层只会通过getService()方法来往下进行访问,于是覆盖了getService()方法之后,则不需要再提供createService()了。这时我们就可以理解ServiceFetcher类的作用了,在系统实现上,Service有可能会通过getService()返回其实例,比如在SingleTon模式下构建的Service。我们不需要基于Service重构,而只需要在使用它的时候通过覆盖getService()来进行灵活地重构,比如这里的AccessibilityManager.getInstance()。

8 覆盖createService()方法。这是更普遍的做法,每一个System Service,都会通过registerService()将createService()构造方法注册到Context环境里,这样当应用程序调用getSystemService()时,在内部实际上会通过createService()来创建一个与Service对应的Proxy对象。我们前面分析过framework的构成,这样的Proxy对象会是XXXManager的形式,于是我们实际上在createService()里会创建ActivityManager之类的对象。

9 覆盖createService()的另一种方法。对于System Service而言,虽然都在系统运行过程中一直存在,但有的会很忙,像Media、Audio、Graphic等,只要有Proxy,便可以响应其调用请求,有一部分则可能长期驻留后台,只是偶尔响应一下请求,比如像我们例子里看到AlarmManager。对于响应度不高的SystemService,一般都会在一个叫servicemanager的守护进程的监管之下,所以我们这里会使用Stub.asInterface()接口方法申请对象,从而保证这一Service不被调用时则可以进入休眠。

在这个整体的执行流程里,比较绕,而且深入代码分析时,我们也会看到在实现时的不一致,风格并非很严谨。但通过中间插入的这层ServiceFetcher,可以让应用程序(或是某种需要使用getSystemService()方法的系统组件)很快找到合适的ServiceProxy端的初始化方法,快速建立起跟RemoteService的通信。

除了getSystemService()方法与bindService()不同以外,在这时我们看不到两者的任何区别。当然,我们在bindService()里也会使用到onServiceConnected()回调方法异步地返回一个IBinder引用,但这也只是出于Service的生命周期考虑的结果。bindService()只是通过Intent找到合适的Service,而具体远程Service的Binder引用,则是通过onServiceConnected()。所以本质上getSystemService()与bindService()只是形式上的区别,本质上是一回事,成功调用之后便可以进行一样的RPC操作请求了。

我们可以注意到getService()与bindService()的一个重要区别,bindService()与unbindService()成对,而getService()只是单独出现。于是,bindService()这种调用机制上的Service,总是在Bounded生命周期里才能对外提供服务,可以做到按需启动,不再需要时便会在合适的时间点被关闭。而getService()所操作的Service则没有什么生命周期,永远在系统里运行并提供服务,这里也需要有种实体可以管理这些Service,当这些Service无人使用时,承载该Service的进程便会进入休眠中,这便是ServiceManager的Stub端所完成的功能。

ServiceManager在Java和Native环境里各有其实现,但在Java端实际上只有Proxy端,而Native环境里实现的servicemanager才具有完整的Proxy与Stub实现。

我们可以先来看ServiceManager.java的实现:

public finalclass ServiceManager {

private staticfinal String TAG ="ServiceManager";

private static IServiceManagersServiceManager;

private static IServiceManagergetIServiceManager() {

if(sServiceManager != null) {

return sServiceManager;

}

sServiceManager =ServiceManagerNative.asInterface(BinderInternal.getContextObject()); 2

return sServiceManager;

}

public static IBindergetService(String name) {

try {

IBinder service = sCache.get(name);

if (service != null) {

return service;

} else {

returngetIServiceManager().getService(name); 1

}

} catch (RemoteException e) {

Log.e(TAG, "error in getService", e);

}

return null;

}

1 每次通过ServiceManager的getService()方法取得一个SystemService的引用,实际上只是通过getIServiceManager()取回一个Proxy对象,然后再调用这个Proxy对象的getService()方法。

2 getIServiceManager(),实际上则是通过IServiceManager接口,访问到一个ServiceManagerNative对象。

代码如此简洁,于是我们可以跟踪ServiceManagerNative的实现。从ServiceManagerNative类的实现上,我们也可以看到基于Binder收发两端的实现,但实际上接收端没有意义,也不会被执行到。代码如下:

package android.os;

import java.util.ArrayList;

public abstractclass ServiceManagerNativeextends Binder implements IServiceManager 1

{

static public IServiceManagerasInterface(IBinder obj)

{

if(obj == null) {

return null;

}

IServiceManager in =

(IServiceManager)obj.queryLocalInterface(descriptor);

if(in != null) {

return in;

}

return new ServiceManagerProxy(obj); 2

}

publicServiceManagerNative()

{

attachInterface(this, descriptor);

}

public boolean onTransact(int code, Parcel data,Parcel reply,int flags)

{

...

}

public IBinderasBinder()

{

return this;

}

}

class ServiceManagerProxy implements IServiceManager {

publicServiceManagerProxy(IBinder remote) {

mRemote = remote;

}

public IBinderasBinder() {

return mRemote;

}

public IBindergetService(String name) throws RemoteException { 3

Parcel data = Parcel.obtain();

Parcel reply = Parcel.obtain();

data.writeInterfaceToken(IServiceManager.descriptor);

data.writeString(name);

mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);

IBinder binder = reply.readStrongBinder();

reply.recycle();

data.recycle();

return binder;

}

public IBindercheckService(String name)throws RemoteException {

return binder;

}

public void addService(Stringname, IBinder service,boolean allowIsolated)

throws RemoteException {

}

public String[]listServices() throws RemoteException {

ArrayList<String> services = new ArrayList<String>();

int n = 0;

while (true) {

}

return array;

}

public voidsetPermissionController(IPermissionController controller)

throws RemoteException {

}

private IBindermRemote;

}

1 从ServiceManagerNative,可以看到,它也是一个抽象类,继承Binder,实现IServiceManager接口。于是它必然会实现asInterface()、asBinder()等Binder所需要的接口方法。但因为它本质上只是起到Proxy作用,作为一个抽象类,它并不可能被实例化,除非有一个非抽象类继承它并实现它所缺少的方法。这种实现在代码层面上没有意义,我们从后面的分析servicemanager的Native实现时也可以看得出来,于是我们虽然看到了onTransact()实现,但实际上它不起作用。

2 这是整个ServiceManagerNative类实现的最有意义的一行。虽然这一行与其他基于IBinder实现的远程类没什么不同,但这一行提供了Proxy接口,这个Proxy接口,则是其他System Service所需要的访问接口。在ServiceManagerNative类的asInterface()方法里,我们会创建并返回一个Proxy对象ServiceManagerPoxy。

3 ServiceManagerProxy对象里实现就没什么特殊之处了。跟会通过Binder访问到Remote Service的其他远程方法一样,会将本地需要调用的方法,将方法名与参数打包,将得到的命令通过Binder发送出去,然后再等着远程执行的返回。

此时,如果系统里有某种实现,在标签同是“android.os.IServiceManager”的Binder通信管道上监听,并响应getService()等方法的调用请求,这时整个基于ServiceManager的模型便完美了。我们可以继续使用ActivityManagerService实现时同样的技巧,继承ServiceManagerNative并且实现一个onTransact()所需要的响应方法,但这样的方式性能不够好,不利于频繁调用。

Java语言环境本身只是一种虚拟机环境,Java虚拟机在实现上强调的是对底层的封装,并不会提供针对操作系统的某种功能,如果我们想实现对底层的访问,则必须使用JNI来访问。比如访问Binder,如果把这样的机制通过指令或是IO拓展的方式直接嵌入到Java语言里,则会引发Android系统与Java语言的更大分裂。于是Binder本身是通过JNI拓展到Java语言里的,这样同时还达到一个高效的目的,虽然Java语言里可以访问到Binder的相应操作接口,但在底层实际上是通过C++实现的更高效的版本。既然Binder已经是C++实现,再通过JNI引入到Java环境里,我们的ServiceManager的Stub实现就没有必要到Java环境里再重复一次了,可以直接在底层将IServiceManager接口所需要的远程方法实现即可。这种方式更符合Java语法习惯、Native实现可以得到更高效ServiceManager,另外还提供了进一步实现NativeSerivce的可能性。既然底层是C++实现的,于是可以将Service的逻辑用C++写出来,再通过Binder直接暴露到应用程序层即可。

读书人网 >Android

热点推荐