ContextImpl 注册service源码分析

private static int sNextPerContextServiceCacheIndex = 0;
private static void registerService(String serviceName,ServiceFetcher fetcher){
    if(!(fetcher instanceof StaticServiceFetcher)){
        fetcher.mContextCacheIndex=sNextPerContextServiceCacheIndex++;
    }
    SYSTEM_SERVICE_MAP.put(serviceName,fetcher);
}
...
省略
...
static class ServiceFetcher{
    int mContextCacheIndex = -1;
    public Object getService(ContextImpl ctx){
        //通过ServiceFetcher类获取 Service;
        ArrayList cache=ctx.mServiceCache; 
        Object service;
        synchronized (cache){
            if(cache.size()==0){
                for(int i=0;i 
 

按照注册顺序mContextCacheIndex=sNextPercontextServiceCacheIndex++;
注册完成后 serverFetcher 缓存在 SYSTEM_SERVICE_MAP 中;
外界获取服务的时候,通过ContextImpl 的 getSystemService(String Name);

public Object getSystemService(String name){
    ServiceFetcher fetcher= SYSTEM_SERVICE_MAP.get(name);
    return fetcher==null?null:fetcher.getService(this);
}

如果单看以上代码会发现是有bug的

if(cache.size()==0){
    for(int i=0;i

如果再获取到service之后,继续registerService 那么mContextCacheIndex增大,那么cache.set 时(注释 A1 )就会出现arrayList index 越界的情况。
所以还要读一下以下部分的代码

static{
    registerService(ACCESSIBILITY_SERVICE,new ServiceFetcher(){
        public Object getService(ContextImpl ctx){
            return new AccessibilityManager.getInstance(ctx);
        }
    })
    ...
registerService(ALARM_SERVICE,new ServiceFetcher(){
        public Object createService(ContextImpl ctx){
            IBinder b=ServiceManager.getService(ALARM_SERVICE);
            IAlarmManager service = IAlarmManager.Stub.asInterface(b);
            return new AlarmManager(service,ctx);
        }
    })
}

通过static代码块保障所有的注册都在使用之前。这样就不存在上面所说的bug了。

未解决问题:

为什么会做了两个缓存
SYSTEM_SERVICE_MAP 注册时缓存。
mServiceCache,获取时getService缓存。

你可能感兴趣的:(ContextImpl 注册service源码分析)