在之前 Android 系统服务管理 ServiceManager 中学习了各种系统服务 Service 都是通过 ServiceManager
来管理的,从 ServiceManager 中来获得系统服务的 Binder 对象引用。这内容涉及到了 ContextImpl
类、SystemServiceRegistry
类、ServiceManager
类、ServiceManagerNative
类等等。
那么问题就来了,ServiceManager 所管理的那些 Service 的 Binder 对象引用又是何时注册添加的呢?
事实上这些服务 Service 是 SystemServer 进程中启动的。
SystemServer 系统服务
SystemServer 是由 Zygote 孵化的第一个进程,它和系统服务有着重要关系,通过 ps 命令,可知其进程名为 system_server
。Zygote 的进程名称为app_process
。
Android 系统中几乎所有的核心服务都在这个进程中,如 ActivityManagerService,PowerManagerService 和 WindowManagerService 等。
Zygote 为启动 SystemService 提供了专门的函数 forkSystemServer
,而不是标准的forkAndSpecialize
函数。
而 SystemServer 的执行主要在其 main 方法中,Android 6.0 的源码中不再是以前 Android 4.x 的 init1,init2 方法了。
/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}
继续跟进 run 方法查看:
private void run() {
try {
// 如果当前系统时间比 1970 年更早,就设置当前系统时间为 1970 年
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
// Here we go!
Slog.i(TAG, "Entered the Android system server!");
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());
// Ensure binder calls into the system always run at foreground priority.
// 确保当前系统进程的 binder 调用,总是运行在前台优先级
BinderInternal.disableBackgroundScheduling(true);
// Prepare the main looper thread (this thread).
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
Looper.prepareMainLooper();
// Initialize native services.加载本地服务
System.loadLibrary("android_servers");
// Check whether we failed to shut down last time we tried.
// This call may not return.
performPendingShutdown();
// Initialize the system context.初始化系统上下文
createSystemContext();
// Create the system service manager.创建系统服务管理
mSystemServiceManager = new SystemServiceManager(mSystemContext);
// 将 mSystemServiceManager 添加到本地服务 LocalServices 的成员 sLocalServiceObjects
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
// Start services.
try {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
// 启动服务代码
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
在 main 方法中删除了一些与虚拟机有关的代码,只关心系统服务的启动就好。
在启动系统服务之前还初始化了系统环境上下文 createSystemContext()
,执行了此方法之后mSystemContext
变量才不会为 null ,关于如何初始化系统环境的上下文 Context ,必须得在写一篇博客单独学习了。
初始化 mSystemContext 之后,就是启动服务了:
- startBootstrapServices(); // 启动引导服务
- startCoreServices(); // 启动核心服务
- startOtherServices(); // 启动其他服务
SystemServer 进程启动系统服务方式
SystemServer 进程启动系统服务有两种方式,分别是 SystemServiceManager 的startService
方式和 ServiceManager 的 addService
方式。
ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
mSystemServiceManager.startService(TelecomLoaderService.class);
startService 方式
通过 SystemServiceManager 的startService(Class<T> serviceClass)
用于启动继承于SystemService
抽象类的服务。
主要功能如下:
- 通过反射创建对应的 SystemService ,并调用其
onStart
方法。 - 同时将创建是 SystemService 添加到 SystemServiceManager 的
mService
集合变量中。
addService 方式
通过 ServiceManager 的addService(String name, IBinder service)
用于初始化继承于 IBinder 的服务。
主要功能如下:
- 将对应服务的 Binder 对象添加到 SystemManager 中去。
之前有学习到 ServiceManager 是系统服务的管家,通过它来获得其他服务。然而,在启动系统服务时,有些服务竟然没有 addService 注册到 ServiceManager 中去。
事实上,有些服务即使在启动时没有注册进去,在启动之后也会注册到 ServiceManager 中去。
通过查看 SystemService
这个抽象类的源码可知,有如下方法:
/**
* Publish the service so it is accessible to other services and apps.
*/
protected final void publishBinderService(String name, IBinder service) {
publishBinderService(name, service, false);
}
/**
* Publish the service so it is accessible to other services and apps.
*/
protected final void publishBinderService(String name, IBinder service,
boolean allowIsolated) {
ServiceManager.addService(name, service, allowIsolated);
}
而 ServiceManager 的对应方法为,最后一个变量设置 true 的话,则表示允许隔离的沙盒进程访问该服务。
/**
* Place a new @a service called @a name into the service
* manager.
*
* @param name the name of the new service
* @param service the service object
* @param allowIsolated set to true to allow isolated sandboxed processes
* to access this service
*/
public static void addService(String name, IBinder service, boolean allowIsolated) {
try {
getIServiceManager().addService(name, service, allowIsolated);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
ServiceManager 启动时机
SystemServer 是一个进程,由 Zygote 孵化的第一个进程,而 ServiceManager 也是一个进程,并且 SystemService 启动系统服务时,可以向 ServiceManager 中注册服务,那么可想而知,ServiceManager 是比 SystemService 先启动的。
ServiceManager 是由 init.rc
进程启动的。
在init.rc
中有如下代码启动 ServiceManager 。
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart healthd
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart drm
由于我编的 Android 源码里面竟然死活没找到上面的代码,附上源码链接地址为: https://android.googlesource.com/platform/system/core/+/android-6.0.0_r1/rootdir/init.rc
就这样,虽然跳过了很多细节的部分,但还是大概的明白了 Android 系统服务管理(ServiceManager)和启动(SystemServer)的流程。
其他的细节部分,每个部分都可在再继续深入学习了。
最后还是附图一张:
参考
- 《Android内核剖析》
- 《深入理解Android》
- http://blog.csdn.net/nightduke1/article/details/44201317
- http://ticktick.blog.51cto.com/823160/1659473
- http://gityuan.com/2016/02/20/android-system-server-2/
知识星球
公众号音视频开发进阶对应的知识星球,一个编程开发领域的专业圈子,贩卖知识和技巧! ※ 入群须知:了解该星球能提供的价值和帮助,在提问时务必阐述好背景,附带相关的信息。 iOS 用户可以加我微信 ezglumes 邀请你进星球,有疑问也可以加我微信咨询。 ※ 星球内容: 基础教程: 在知识星球连载的干货教程,可以在专栏中找到,随着时间的推移,教程也会越来越多: - 音视频基础概念 - WebRTC 入门教程及源码实践 - 播放器教程及源码实践 - OpenGL 和特效开发教程 - Vulkan 入门教程 部分内容可以在博客 https://glumes.com 中检索到,后面会在星球里持续更新. 干货分享: 涵盖了移动开发和音视频工程领域的绝大部分,从项目实战角度出发,提升能力,包括但不限于以下领域: - Android/iOS 移动开发 - Camera 开发 - 短视频编辑 SDK 项目实践 - 在线直播和推流 - WebRTC 开发 - 播放器基础和提高 - OpenGL 图像渲染及特效开发 - C++ 基础和提高 - FFmpeg 使用和分析 - 干货资源和书籍分享 不止于技术方面的,各种 IT 新闻、茶余饭后、生活趣事也欢迎大家分享!!! 技术答疑解惑: 针对上述基础教程和干货分享的答疑,另外还有音视频和 IT 开发中的各种交流讨论。 - 基础知识点答疑 - 工业项目实践答疑 - 问题排查思路分析 一个 BUG 排查很久,不如来星球里提个问题,效率提升百倍。 求职和面试辅导: 一站式职场服务,每份工作都值得用心对待!!! - 面试题和面试经验分享 - 简历修改和模拟面试 - 大厂内推和信息同步 - 职场经验分享 - 职业规划和发展分析 ※ 星主和合伙人介绍 星主是公众号音视频开发进阶的作者,也是网站 https://glumes.com 的作者,曾参与过抖音、剪映等头部音视频 APP 底层 SDK 的开发。 合伙人也是在头条、快手从事音视频架构师的职位,具有多年的音视频开发经验,能力圈覆盖了音视频的绝大多数领域,资深音视频从业人员为你保驾护航。
微信公众号
扫描下面的二维码关注我的微信公众号《音视频开发进阶》,推送更多精彩内容!
添加我的微信 ezglumes 拉你入音视频与图形图像技术群一起交流学习~

原创文章,转载请注明来源: Android 系统服务启动 SystemServer