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系统服务获取的资料请关注编程网其它相关文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341