Android系统服务是如何获取的
关于获取系统服务的猜想
android获取系统服务一般都需要用getsystemservice指定系统服务名称获取:
val wm = getsystemservice(context.window_service) as windowmanager
在实际开发中,当我们需要编写提供某一业务流程处理的manager,通常会实现为单例。那么上面那行代码背后发生了什么,为什么android不使用单例模式呢?下面我们观察android是如何设计获取系统服务的,它如何从应用侧到达系统侧。
可以思考一下,不在每个服务中单独使用单例的原因大概是因为android提供的系统服务众多,都使用getsystemservice方法相当于提供了统一的入口。同时因为方法参数中的服务名称字符串,可以提供一个map来统一存放各种服务实例,这与单例模式十分接近,相当于统一管理各种单例的变种。那么事实是不是这样呢?(下方源码只保留关键代码,api 30)
获取系统服务源码实现
各种继承或者持有context的组件的getsystemservice方法都会调用contextimpl的同名方法:
//contextimpl.java public object getsystemservice(string name) { return systemserviceregistry.getsystemservice(this, name); }
systemserviceregistry一看就是统一注册系统服务的地方:
//systemserviceregistry.java public static object getsystemservice(contextimpl ctx, string name) { final servicefetcher<?> fetcher = system_service_fetchers.get(name); final object ret = fetcher.getservice(ctx); return ret; }
这里我们确实发现了map,可却不是从string到系统服务的map,system_service_fetchers的类型为map<string, servicefetcher<?>>。
//systemserviceregistry.java static abstract interface servicefetcher<t> { t getservice(contextimpl ctx); }
这个systemserviceregistry中的内部接口servicefetcher,看上去像是各种系统服务的工厂接口。我们看它的实现类:
//systemserviceregistry.java static abstract class cachedservicefetcher<t> implements servicefetcher<t> { private final int mcacheindex; cachedservicefetcher() { mcacheindex = sservicecachesize++; } @override public final t getservice(contextimpl ctx) { final object[] cache = ctx.mservicecache; t ret = null; t service = (t) cache[mcacheindex]; if (service != null) { ret = service; } else { service = createservice(ctx); cache[mcacheindex] = service; ret = service; } return ret; } public abstract t createservice(contextimpl ctx) throws servicenotfoundexception; }
getservice方法精简了大量保证线程安全的同步措施,只保留了最核心的逻辑。可以看到另有一个类型为object[]的数组ctx.mservicecache,getservice从中用下标mcacheindex获取系统服务,如果服务为空则使用createservice方法创建服务并放在数组中。可以说,这个ctx.mservicecache数组起到了我们最初设想的从string到系统服务的map的存放所有系统服务的作用。这个映射变为了:
假象的映射(从string到系统服务) <=> system_service_fetchers映射(从string到servicefetcher) + ctx.mservicecache数组(servicefetcher中的mcacheindex下标到系统服务)
这个system_service_fetchers映射在systemserviceregistry的静态初始化快中被统一填充,同时提供了上方没有实现的createservice:
//systemserviceregistry.java static { registerservice(context.window_service, windowmanager.class, new cachedservicefetcher<windowmanager>() { @override public windowmanager createservice(contextimpl ctx) { return new windowmanagerimpl(ctx); }}); } private static <t> void registerservice(@nonnull string servicename, @nonnull class<t> serviceclass, @nonnull servicefetcher<t> servicefetcher) { system_service_fetchers.put(servicename, servicefetcher); }
systemserviceregistry类初始化时,ctx.mservicecache系统服务数组还是空的,当某一系统服务需要时,上方cachedservicefetcher中getservice会调用createservice创建服务并存放在特定mcacheindex下标中。
总结一下就是:在android获取系统服务的流程中,使用工厂模式创建系统服务,使用map管理工厂,使用数组管理系统服务实例。每种服务在每个contextimpl中的数组中最多只有一个,且使用前不会提前创建,这点和单例的懒汉式是一致的。
真正的系统服务提供者
我们知道android framework中系统服务是运行在系统进程中,需要通过binder机制与应用进程通信,如果我们不考虑系统侧实现,上面拿到的类真的应用侧的binder类么?其实并不全是,依旧查看工厂类中的工厂方法:
- 上面获取到的服务类,有些类的确是系统侧的系统服务对应到应用侧的binder类,比如alarmmanager:
//systemserviceregistry.java registerservice(context.alarm_service, alarmmanager.class, new cachedservicefetcher<alarmmanager>() { @override public alarmmanager createservice(contextimpl ctx) throws servicenotfoundexception { ibinder b = servicemanager.getserviceorthrow(context.alarm_service); ialarmmanager service = ialarmmanager.stub.asinterface(b); return new alarmmanager(service, ctx); }});
- 有些则是对这些binder类的直接封装,比如activitymanager:
//systemserviceregistry.java registerservice(context.activity_service, activitymanager.class, new cachedservicefetcher<activitymanager>() { @override public activitymanager createservice(contextimpl ctx) { return new activitymanager(ctx.getoutercontext(), ctx.mmainthread.gethandler()); }});
其中大量的方法使用getservice与gettaskservice进行委托:
//activitymanager.java public void killuid(int uid, string reason) { try { getservice().killuid(userhandle.getappid(uid), userhandle.getuserid(uid), reason); } catch (remoteexception e) { throw e.rethrowfromsystemserver(); } } public list<runningtaskinfo> getrunningtasks(int maxnum) throws securityexception { try { return gettaskservice().gettasks(maxnum); } catch (remoteexception e) { throw e.rethrowfromsystemserver(); } } public static iactivitymanager getservice() { return iactivitymanagersingleton.get(); } private static iactivitytaskmanager gettaskservice() { return activitytaskmanager.getservice(); }
而getservice与gettaskservice都是单例方法,另外使用servicemanager获取真正的binder类。
- 另外还有些系统服务为了便于使用,封装得更加复杂,比如windowmanager:
registerservice(context.window_service, windowmanager.class, new cachedservicefetcher<windowmanager>() { @override public windowmanager createservice(contextimpl ctx) { return new windowmanagerimpl(ctx); }});
这里的各不同context的windowmanagerimpl会统一调用到windowmanagerglobal,而windowmanagerglobal在addview时会创建viewrootimpl,并将binder类windowsession传递给viewrootimpl,由viewrootimpl完成与wms通信的工作。
以上实现了获取系统服务时从应用侧到达系统侧的过程。
以上就是android系统服务是如何获取的的详细内容,更多关于android系统服务获取的资料请关注其它相关文章!
上一篇: 任正非最新发言汇总:华为根本不会"死" 正处在最佳状态
下一篇: 你该吃药了