我们可以在Activity、Service中获取到服务的管理对象,从而可以让服务工作,完成客户端的请求。
在aidl文件编译生成的java文件中,有关服务管理对象(XXManager)、服务接口(IXXManager)、根(IXXManager.Stub)、服务(XXManagerService)、服务代理(IXXManager.Stub.Proxy)之间的大致类关系如图:
具体可以看下aidl文件编译后生成的Java文件。
现在,在Activity中通过获取PowerManager服务为例:
1、在Activity中通过:PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);获取电源服务管理对象。
对于PowerManager类中的构造:
public PowerManager(Context context, IPowerManager service, Handler handler) {
mContext = context;
mService = service;
mHandler = handler;
}
其上的IPowerManager service参数给了 PowerManager中的成员变量mService,进而可以调用代理类中相应的方法,比如:
PowerManager中的方法,
public boolean isScreenOn() {
try {
return mService.isScreenOn();
} catch (RemoteException e) {
return false;
}
}
2、进入Context类中,查看方法getSystemService的工作机制,此类中方法为:
public abstract Object getSystemService(String name);
3、上面方法是抽象的,看其实现类ContextImpl:
@Override
public Object getSystemService(String name) {
ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
return fetcher == null ? null : fetcher.getService(this);
}
说明:
//以String为key,ServiceFetcher为value
private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP = new HashMap<String, ServiceFetcher>();
添加元素到的操作在方法:
private static void registerService(String serviceName,
ServiceFetcher fetcher) {
if (!(fetcher instanceof StaticServiceFetcher)) {
fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;
}
SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
}
而实际上,调用这个发给方法的实在ContextImpl中的一个静态代码块中:
static {
................
registerService(POWER_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(POWER_SERVICE);
IPowerManager service = IPowerManager.Stub.asInterface(b);
return new PowerManager(ctx.getOuterContext(), service,
ctx.mMainThread.getHandler());
}
});
................
}
通过静态代码块调用的方法,将相应的服务管理对象添加到了SYSTEM_SERVICE_MAP中。
4、对于静态代码块中的一个内部方法等下再看,回到getSystemService方法中的return fetcher == null ? null : fetcher.getService(this);
看下ServiceFetcher,源码如下:
/**
* Override this class when the system service constructor needs a
* ContextImpl. Else, use StaticServiceFetcher below.
*/
/* package */static class ServiceFetcher {
int mContextCacheIndex = -1;
/**
* Main entrypoint; only override if you don't need caching.
*/
public Object getService(ContextImpl ctx) {
ArrayList<Object> cache = ctx.mServiceCache;
Object service;
synchronized (cache) {
if (cache.size() == 0) {
// Initialize the cache vector on first access.
// At this point sNextPerContextServiceCacheIndex
// is the number of potential services that are
// cached per-Context.
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;
}
}
/**
* Override this to create a new per-Context instance of the service.
* getService() will handle locking and caching.
*/
public Object createService(ContextImpl ctx) {
throw new RuntimeException("Not implemented");
}
}
/**
* Override this class for services to be cached process-wide.
*/
abstract static class StaticServiceFetcher extends ServiceFetcher {
private Object mCachedInstance;
@Override
public final Object getService(ContextImpl unused) {
synchronized (StaticServiceFetcher.this) {
Object service = mCachedInstance;
if (service != null) {
return service;
}
return mCachedInstance = createStaticService();
}
}
public abstract Object createStaticService();
}
上面的代码中可以通过getService调用createService方法,分别从集合HashMap中取得的ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);会调用静态代码中相应的方法,虽然在return fetcher == null ? null : fetcher.getService(this);只是调用了getService方法,但是前面代码也可一知道。
5、回到静态代码中的内部方法:
// Note: this was previously cached in a static variable, but
// constructed using mMainThread.getHandler(), so converting
// it to be a regular Context-cached service...
//##########################
registerService(POWER_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(POWER_SERVICE);
IPowerManager service = IPowerManager.Stub.asInterface(b);
return new PowerManager(ctx.getOuterContext(), service,
ctx.mMainThread.getHandler());
}
});
获取一个电源管理,并且最终返回给我们初始调用的方法getSystemService。
6、内部方法方法体:
IBinder b = ServiceManager.getService(POWER_SERVICE);
IPowerManager service = IPowerManager.Stub.asInterface(b);
return new PowerManager(ctx.getOuterContext(), service,
ctx.mMainThread.getHandler());
第一行:IBinder b = ServiceManager.getService(POWER_SERVICE);从ServiceManager服务注册管理类中取出PowerManagerService对象,可以看下是怎么添加上去的,见下面代码。
其实在SystemServer中:
power = new PowerManagerService();
ServiceManager.addService(Context.POWER_SERVICE, power);
第二行:IPowerManager service = IPowerManager.Stub.asInterface(b);获取代理对象。
调用的是IPowerManager.Stub.asInterface(b)方法,看下AIDL文件编译生成的java文件,就会知道。
这是个例子代码:
public static com.example.testactivitystart.HH asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.testactivitystart.HH))) {
return ((com.example.testactivitystart.HH)iin);
}
return new com.example.testactivitystart.HH.Stub.Proxy(obj);
}
最终通过return new com.example.testactivitystart.HH.Stub.Proxy(obj);获取该服务相对应的服务代理对象。
第三行:return new PowerManager(ctx.getOuterContext(), service,ctx.mMainThread.getHandler());
回到PowerManager类中的构造方法,
/**
* {@hide}
*/
public PowerManager(Context context, IPowerManager service, Handler handler) {
mContext = context;
mService = service;
mHandler = handler;
}
mService = service;电源服务代理对象给了电源管理中的成员变量mService。
=============================================================================================
Activity:
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
pm.isScreenOn();
===================================================================================================
客户段通过电源管理pm.isScreenOn()方法,
public boolean isScreenOn() {
try {
return mService.isScreenOn();
} catch (RemoteException e) {
return false;
}
}
继而,调用电源服务代理中的isScreenOn()方法。
最后,调用电源服务中的方法isScreenOn()。他们之间的联系通过Binder机制实现。